방재호 commited on
Commit
5636c1c
·
1 Parent(s): fc73761
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .DS_Store +0 -0
  2. extensions/.DS_Store +0 -0
  3. extensions/openOutpaint-webUI-extension/.DS_Store +0 -0
  4. extensions/openOutpaint-webUI-extension/LICENSE +21 -0
  5. extensions/openOutpaint-webUI-extension/README.MD +22 -0
  6. extensions/openOutpaint-webUI-extension/__pycache__/preload.cpython-310.pyc +0 -0
  7. extensions/openOutpaint-webUI-extension/__pycache__/preload.cpython-311.pyc +0 -0
  8. extensions/openOutpaint-webUI-extension/app/.DS_Store +0 -0
  9. extensions/openOutpaint-webUI-extension/app/.devtools/README.md +12 -0
  10. extensions/openOutpaint-webUI-extension/app/.devtools/lint.sh +21 -0
  11. extensions/openOutpaint-webUI-extension/app/.devtools/sethooks.ps1 +4 -0
  12. extensions/openOutpaint-webUI-extension/app/.devtools/sethooks.sh +3 -0
  13. extensions/openOutpaint-webUI-extension/app/.devtools/updatehashes.ps1 +27 -0
  14. extensions/openOutpaint-webUI-extension/app/.devtools/updatehashes.sh +128 -0
  15. extensions/openOutpaint-webUI-extension/app/.gitattributes +1 -0
  16. extensions/openOutpaint-webUI-extension/app/.githooks/linux/pre-commit +9 -0
  17. extensions/openOutpaint-webUI-extension/app/.githooks/windows/pre-commit +9 -0
  18. extensions/openOutpaint-webUI-extension/app/.github/ISSUE_TEMPLATE/bug_report.yml +91 -0
  19. extensions/openOutpaint-webUI-extension/app/.github/ISSUE_TEMPLATE/feature_request.yml +48 -0
  20. extensions/openOutpaint-webUI-extension/app/.github/workflows/autoformat.yml +22 -0
  21. extensions/openOutpaint-webUI-extension/app/.github/workflows/cachebusting.yml +26 -0
  22. extensions/openOutpaint-webUI-extension/app/.gitignore +12 -0
  23. extensions/openOutpaint-webUI-extension/app/.prettierrc.json +19 -0
  24. extensions/openOutpaint-webUI-extension/app/CONTRIBUTING.md +63 -0
  25. extensions/openOutpaint-webUI-extension/app/LICENSE +21 -0
  26. extensions/openOutpaint-webUI-extension/app/README.md +92 -0
  27. extensions/openOutpaint-webUI-extension/app/css/colors.css +10 -0
  28. extensions/openOutpaint-webUI-extension/app/css/fonts.css +4 -0
  29. extensions/openOutpaint-webUI-extension/app/css/icons.css +198 -0
  30. extensions/openOutpaint-webUI-extension/app/css/index.css +678 -0
  31. extensions/openOutpaint-webUI-extension/app/css/layers.css +71 -0
  32. extensions/openOutpaint-webUI-extension/app/css/ui/generic.css +451 -0
  33. extensions/openOutpaint-webUI-extension/app/css/ui/history.css +38 -0
  34. extensions/openOutpaint-webUI-extension/app/css/ui/layers.css +206 -0
  35. extensions/openOutpaint-webUI-extension/app/css/ui/notifications.css +253 -0
  36. extensions/openOutpaint-webUI-extension/app/css/ui/tool/colorbrush.css +42 -0
  37. extensions/openOutpaint-webUI-extension/app/css/ui/tool/dream.css +3 -0
  38. extensions/openOutpaint-webUI-extension/app/css/ui/tool/stamp.css +56 -0
  39. extensions/openOutpaint-webUI-extension/app/css/ui/toolbar.css +94 -0
  40. extensions/openOutpaint-webUI-extension/app/css/ui/workspace.css +59 -0
  41. extensions/openOutpaint-webUI-extension/app/defaultscripts.json +16 -0
  42. extensions/openOutpaint-webUI-extension/app/docs/.DS_Store +0 -0
  43. extensions/openOutpaint-webUI-extension/app/favicon.ico +0 -0
  44. extensions/openOutpaint-webUI-extension/app/index.html +591 -0
  45. extensions/openOutpaint-webUI-extension/app/js/config.js +52 -0
  46. extensions/openOutpaint-webUI-extension/app/js/defaults.js +28 -0
  47. extensions/openOutpaint-webUI-extension/app/js/extensions.js +196 -0
  48. extensions/openOutpaint-webUI-extension/app/js/global.js +61 -0
  49. extensions/openOutpaint-webUI-extension/app/js/index.js +1685 -0
  50. extensions/openOutpaint-webUI-extension/app/js/initalize/debug.populate.js +33 -0
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
extensions/.DS_Store CHANGED
Binary files a/extensions/.DS_Store and b/extensions/.DS_Store differ
 
extensions/openOutpaint-webUI-extension/.DS_Store ADDED
Binary file (6.15 kB). View file
 
extensions/openOutpaint-webUI-extension/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2022 tim h
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.
extensions/openOutpaint-webUI-extension/README.MD ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ In this repo lives a mighty handy little wrapper for adding [openOutpaint](https://github.com/zero01101/openOutpaint) to [AUTOMATIC1111 webUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) directly as a native extension.
2
+
3
+ Please see the respective READMEs and wikis for each of the above projects for a more comprehensive understanding of their feature sets.
4
+
5
+ This extension also adds buttons to send output from webUI txt2img and img2img tools directly to openOutpaint which will also include the prompts used for convenience.
6
+
7
+ **_2023-01-23: new `--lock-oo-submodule` commandline argument if you want to roll back to a previous version of openOutpaint and keep it there - be sure to install/run openOutpaint extension at least once before enabling this flag_**
8
+
9
+ **Note: Requires `--api` flag enabled in your webui-user launch script!**
10
+
11
+ **_FURTHER NOTE: the commandline flag `--gradio-debug` disables custom API routes and completely breaks openOutpaint. please remove it from your COMMANDLINE_ARGS before running openOutpaint._**
12
+
13
+ **_EVEN FURTHER NOTE: [PLEASE SEE DOCUMENTATION REGARDING NEW HRfix FEATURES](https://github.com/zero01101/openOutpaint/wiki/Manual#hrfix) IMPLEMENTED AS OF webUI COMMIT [ef27a18](https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/ef27a18b6b7cb1a8eebdc9b2e88d25baf2c2414d)_**
14
+
15
+ ![image](https://user-images.githubusercontent.com/1649724/209033089-fb908d92-0c52-4165-a6a3-e6e9f28b032d.png)
16
+
17
+ ### surprising incompatibilities
18
+
19
+ **_COLAB USERS: you may experience issues installing openOutpaint (and other webUI extensions) - there is a workaround that has been discovered and tested against [TheLastBen's fast-stable-diffusion](https://github.com/TheLastBen/fast-stable-diffusion). Please see [this discussion](https://github.com/TheLastBen/fast-stable-diffusion/discussions/1161) containing the workaround, which requires adding a command into the final cell of the colab, as well as setting `Enable_API` to `True`._**
20
+
21
+ - [microsoft editor extension for chrome/edge seems to disable the overmask slider](https://github.com/zero01101/openOutpaint/discussions/88#discussioncomment-4498341)
22
+ - ~~[duckduckgo privacy extension for firefox breaks outpainting, resulting in pure black output](https://github.com/zero01101/openOutpaint-webUI-extension/issues/3#issuecomment-1367694000) - add an exception for your openOutpaint host (likely localhost or 127.0.0.1)~~ should be fixed as of [b128943](https://github.com/zero01101/openOutpaint/commit/b128943f0c94970600fdc1c98bfec22de619866f)
extensions/openOutpaint-webUI-extension/__pycache__/preload.cpython-310.pyc ADDED
Binary file (505 Bytes). View file
 
extensions/openOutpaint-webUI-extension/__pycache__/preload.cpython-311.pyc ADDED
Binary file (650 Bytes). View file
 
extensions/openOutpaint-webUI-extension/app/.DS_Store ADDED
Binary file (6.15 kB). View file
 
extensions/openOutpaint-webUI-extension/app/.devtools/README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # openOutpaint DevTools
2
+
3
+ This is a folder containing some handy scripts to help developers to automate workflows and write code in openOutpaint's standards.
4
+ All scripts must be run from the root of the project.
5
+
6
+ ## `sethooks.sh` and `sethooks.ps1` scripts
7
+
8
+ These scripts will setup git hooks for this project. Hooks are mainly for cache busting purposes for now. It is recommended to run this script and setup hooks before any commits are made.
9
+
10
+ ## `lint.sh` script
11
+
12
+ Uses `npm` to install prettier and lint javascript, html and css files according to `.prettierrc.json`. This script will install node modules locally, so editors with prettier support are recommended over this script.
extensions/openOutpaint-webUI-extension/app/.devtools/lint.sh ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/bash
2
+
3
+ if ! which npx 2>&1 > /dev/null; then
4
+ echo "[lint] npm/npx is not installed"
5
+ exit 1
6
+ fi
7
+
8
+ npx prettier > /dev/null || npm install prettier && echo "[lint] We have 'prettier'"
9
+ npx eslint > /dev/null || npm install eslint && echo "[lint] We have 'eslint'"
10
+ npx prettier-eslint > /dev/null || npm install prettier-eslint-cli && echo "[lint] We have 'prettier-eslint'"
11
+
12
+ echo "[lint] Linting JavaScript files..."
13
+ npx prettier-eslint --write "**/*.js"
14
+ echo "[lint] Linting HTML files..."
15
+ npx prettier-eslint --write "**/*.html"
16
+ echo "[lint] Linting CSS files..."
17
+ npx prettier-eslint --write "**/*.css"
18
+ echo "[lint] Linting MarkDown files"
19
+ npx prettier-eslint --write "**/*.md"
20
+
21
+ echo "[lint] Finished Linting."
extensions/openOutpaint-webUI-extension/app/.devtools/sethooks.ps1 ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ git config core.eol lf
2
+ git config core.autocrlf input
3
+
4
+ git config core.hooksPath .githooks/windows
extensions/openOutpaint-webUI-extension/app/.devtools/sethooks.sh ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ #!/usr/bin/sh
2
+
3
+ git config core.hooksPath .githooks/linux
extensions/openOutpaint-webUI-extension/app/.devtools/updatehashes.ps1 ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Updates html files with cache busting urls including file hashes.
2
+
3
+ # Actual file processing
4
+ $htmlfiles = Get-ChildItem -Path . -Recurse -Filter "*.html" | Where {$_.FullName -notlike "*\node_modules\*"} | Resolve-path -relative
5
+ foreach ($htmlfile in $htmlfiles) {
6
+ Write-Host "[info] Processing '${htmlfile}' for cache busting..." -ForegroundColor Blue
7
+
8
+ $resfiles = (@(Get-ChildItem -Path . -Recurse -Filter "*.css") + (Get-ChildItem -Path . -Recurse -Filter "*.js")) | Resolve-Path -relative
9
+
10
+ if ($args[0] -eq "gitadd") {
11
+ $resfiles = (git status -s | Select-String -Pattern "[A-Z] .+") | ForEach-Object { -split $_.Line | Select-Object -Last 1 }
12
+ }
13
+
14
+ foreach ($resfile in $resfiles) {
15
+ $resfile = $resfile -replace '\\', '/' -replace '\./', ''
16
+ # Check if resource is used in html file
17
+ if ($null -ne (Select-String -Path $htmlfile -Pattern $resfile)) {
18
+ $hash = (Get-FileHash $resfile -Algorithm SHA1).Hash
19
+
20
+ # This is just for cache busting...
21
+ # If 7 first characters of SHA1 is okay for git, it should be more than enough for us
22
+ $hash = $hash.Substring(0, 7).ToLower()
23
+
24
+ (Get-Content -Raw -Path $htmlfile).replace('\r\n', "\n") -replace "$resfile(\?v=[a-z0-9]+)?", "${resfile}?v=$hash" | Set-Content $htmlfile
25
+ }
26
+ }
27
+ }
extensions/openOutpaint-webUI-extension/app/.devtools/updatehashes.sh ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/bash
2
+ #
3
+ # Updates html files with cache busting urls including file hashes.
4
+
5
+ # Setup colors
6
+ # Reset
7
+ Color_Off='\033[0m' # Text Reset
8
+
9
+ # Regular Colors
10
+ Black='\033[0;30m' # Black
11
+ Red='\033[0;31m' # Red
12
+ Green='\033[0;32m' # Green
13
+ Yellow='\033[0;33m' # Yellow
14
+ Blue='\033[0;34m' # Blue
15
+ Purple='\033[0;35m' # Purple
16
+ Cyan='\033[0;36m' # Cyan
17
+ White='\033[0;37m' # White
18
+
19
+ # Bold
20
+ BBlack='\033[1;30m' # Black
21
+ BRed='\033[1;31m' # Red
22
+ BGreen='\033[1;32m' # Green
23
+ BYellow='\033[1;33m' # Yellow
24
+ BBlue='\033[1;34m' # Blue
25
+ BPurple='\033[1;35m' # Purple
26
+ BCyan='\033[1;36m' # Cyan
27
+ BWhite='\033[1;37m' # White
28
+
29
+ # Underline
30
+ UBlack='\033[4;30m' # Black
31
+ URed='\033[4;31m' # Red
32
+ UGreen='\033[4;32m' # Green
33
+ UYellow='\033[4;33m' # Yellow
34
+ UBlue='\033[4;34m' # Blue
35
+ UPurple='\033[4;35m' # Purple
36
+ UCyan='\033[4;36m' # Cyan
37
+ UWhite='\033[4;37m' # White
38
+
39
+ # Background
40
+ On_Black='\033[40m' # Black
41
+ On_Red='\033[41m' # Red
42
+ On_Green='\033[42m' # Green
43
+ On_Yellow='\033[43m' # Yellow
44
+ On_Blue='\033[44m' # Blue
45
+ On_Purple='\033[45m' # Purple
46
+ On_Cyan='\033[46m' # Cyan
47
+ On_White='\033[47m' # White
48
+
49
+ # High Intensity
50
+ IBlack='\033[0;90m' # Black
51
+ IRed='\033[0;91m' # Red
52
+ IGreen='\033[0;92m' # Green
53
+ IYellow='\033[0;93m' # Yellow
54
+ IBlue='\033[0;94m' # Blue
55
+ IPurple='\033[0;95m' # Purple
56
+ ICyan='\033[0;96m' # Cyan
57
+ IWhite='\033[0;97m' # White
58
+
59
+ # Bold High Intensity
60
+ BIBlack='\033[1;90m' # Black
61
+ BIRed='\033[1;91m' # Red
62
+ BIGreen='\033[1;92m' # Green
63
+ BIYellow='\033[1;93m' # Yellow
64
+ BIBlue='\033[1;94m' # Blue
65
+ BIPurple='\033[1;95m' # Purple
66
+ BICyan='\033[1;96m' # Cyan
67
+ BIWhite='\033[1;97m' # White
68
+
69
+ # High Intensity backgrounds
70
+ On_IBlack='\033[0;100m' # Black
71
+ On_IRed='\033[0;101m' # Red
72
+ On_IGreen='\033[0;102m' # Green
73
+ On_IYellow='\033[0;103m' # Yellow
74
+ On_IBlue='\033[0;104m' # Blue
75
+ On_IPurple='\033[0;105m' # Purple
76
+ On_ICyan='\033[0;106m' # Cyan
77
+ On_IWhite='\033[0;107m' # White
78
+
79
+ # Check requirements
80
+ if ! which echo > /dev/null
81
+ then
82
+ exit -1
83
+ fi
84
+
85
+ required_programs=(find grep cut sed sha1sum)
86
+
87
+ for program in $required_programs
88
+ do
89
+ if ! which $program > /dev/null
90
+ then
91
+ echo -e "${Red}[error] Requires '$program' command to be installed${Color_Off}"
92
+ exit -1
93
+ fi
94
+ done
95
+
96
+ # Actual file processing
97
+ for htmlfile in $(find -type f -name \*.html -not -path "./node_modules/*")
98
+ do
99
+ echo -e "${BIBlue}[info] Processing '${htmlfile}' for cache busting...${Color_Off}"
100
+
101
+ LIST=$(find -type f -regex '.*\.css\|.*\.js' -not -path "./node_modules/*" | sed 's/\.\///g')
102
+
103
+ if [ "$1" = "gitadd" ]
104
+ then
105
+ LIST=$(git status -s | grep -oE "[A-Z] .+" | cut -d" " -f3)
106
+ fi
107
+
108
+ for resourcefile in $LIST
109
+ do
110
+ # Check if resource is used in html file
111
+ resourceusage=$(grep -i "$resourcefile" "$htmlfile")
112
+ if [ $? -eq 0 ]
113
+ then
114
+ # This is just for cache busting...
115
+ # If 7 first characters of SHA1 is okay for git, it should be more than enough for us
116
+ hash="$(sha1sum $resourcefile | cut -d' ' -f1 | head -c 7)"
117
+
118
+ # Check if resource hash is already correct
119
+ if ! echo "$resourceusage" | grep -i "=$hash\"" > /dev/null
120
+ then
121
+ escaped=$(echo $resourcefile | sed 's/\//\\\//g' | sed 's/\./\\./g')
122
+ sed -Ei "s/${escaped}(\?v=[a-z0-9]+)?/${escaped}?v=${hash}/g" "$htmlfile"
123
+
124
+ echo -e "${BIBlue}[info]${Color_Off} Updated resource ${resourcefile} to hash ${hash}"
125
+ fi
126
+ fi
127
+ done
128
+ done
extensions/openOutpaint-webUI-extension/app/.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ * text eol=lf
extensions/openOutpaint-webUI-extension/app/.githooks/linux/pre-commit ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ #
3
+ # Script to perform some basic operations to the code before committing.
4
+
5
+ # Adds file hashes to html script imports for cache busting purposes
6
+ sh .devtools/updatehashes.sh gitadd
7
+
8
+ # Adds file to current commit
9
+ git add "**.html"
extensions/openOutpaint-webUI-extension/app/.githooks/windows/pre-commit ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ #
3
+ # Script to perform some basic operations to the code before committing.
4
+
5
+ # Adds file hashes to html script imports for cache busting purposes
6
+ powershell .devtools/updatehashes.ps1 gitadd
7
+
8
+ # Adds file to current commit
9
+ git add "**.html"
extensions/openOutpaint-webUI-extension/app/.github/ISSUE_TEMPLATE/bug_report.yml ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Bug Report
2
+ description: You think somethings is broken in the UI
3
+ title: "[Bug]: "
4
+ labels: ["bug"]
5
+ assignees: zero01101, seijihariki
6
+
7
+ body:
8
+ - type: markdown
9
+ attributes:
10
+ value: |
11
+ *Please complete this form with as much detailed information as possible.*
12
+ - type: textarea
13
+ id: what-did
14
+ attributes:
15
+ label: What happened?
16
+ description: What happened that you weren't expecting, or what happened incorrectly?
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: steps
21
+ attributes:
22
+ label: Steps to reproduce the problem
23
+ description: Please provide us with precise step-by-step information on how to reproduce the issue
24
+ value: |
25
+ 1. Go to ....
26
+ 2. Press ....
27
+ 3. ... [etc]
28
+ validations:
29
+ required: true
30
+ - type: textarea
31
+ id: what-should
32
+ attributes:
33
+ label: What should have happened?
34
+ description: Describe what you believe should have ocurred instead of what actually happened.
35
+ validations:
36
+ required: true
37
+ - type: input
38
+ id: commit
39
+ attributes:
40
+ label: Commit where the problem happens
41
+ description: Which commit are you running? (i.e. https://github.com/zero01101/openOutpaint/commit/bf21c19ae352800d9e1b37bb490e817b6848e533, bf21c19)
42
+ validations:
43
+ required: true
44
+ - type: dropdown
45
+ id: platforms
46
+ attributes:
47
+ label: What platforms do you use to access openOutpaint?
48
+ multiple: true
49
+ options:
50
+ - Windows
51
+ - Linux
52
+ - MacOS
53
+ - iOS
54
+ - Android
55
+ - Other/Cloud
56
+ validations:
57
+ required: true
58
+ - type: dropdown
59
+ id: browsers
60
+ attributes:
61
+ label: What browsers do you use to access the UI ?
62
+ multiple: true
63
+ options:
64
+ - Mozilla Firefox
65
+ - Google Chrome
66
+ - Brave
67
+ - Apple Safari
68
+ - Microsoft Edge
69
+ - Opera
70
+ - Other (please list in additional information)
71
+ validations:
72
+ required: true
73
+ - type: textarea
74
+ id: browser-extensions
75
+ attributes:
76
+ label: Browser Extensions/Addons
77
+ description: Please list all browser extensions/addons you have running. Some have been known to cause issues with openOutpaint.
78
+ validations:
79
+ required: true
80
+ - type: textarea
81
+ id: webui-commandline
82
+ attributes:
83
+ label: AUTOMATIC1111 webUI Commandline Arguments
84
+ description: Please list all used commandline arguments passed to A1111 webUI (i.e. `--api`).
85
+ validations:
86
+ required: true
87
+ - type: textarea
88
+ id: misc
89
+ attributes:
90
+ label: Additional information
91
+ description: Please provide us with any relevant additional information, context, screenshots, etc.
extensions/openOutpaint-webUI-extension/app/.github/ISSUE_TEMPLATE/feature_request.yml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Feature request
2
+ description: Suggest an idea for this project
3
+ title: "[Feature Request]: "
4
+ labels: ["enhancement"]
5
+ assignees: zero01101, seijihariki
6
+
7
+ body:
8
+ - type: markdown
9
+ attributes:
10
+ value: |
11
+ *Please complete this form with as much detailed information as possible.*
12
+ - type: textarea
13
+ id: related
14
+ attributes:
15
+ label: Is your feature request related to a problem? Please describe.
16
+ description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: feature
21
+ attributes:
22
+ label: Describe the solution you'd like
23
+ description: A clear and concise description of what you want to happen, preferably with example use-case scenario.
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: workflow
28
+ attributes:
29
+ label: Proposed workflow
30
+ description: Please provide us with step by step information on how you'd like the feature to be accessed and used
31
+ value: |
32
+ 1. Go to ....
33
+ 2. Press ....
34
+ 3. ...
35
+ validations:
36
+ required: true
37
+ - type: textarea
38
+ id: alternatives
39
+ attributes:
40
+ label: Describe alternatives you've considered
41
+ description: A clear and concise description of any alternative solutions or features you've considered.
42
+ validations:
43
+ required: true
44
+ - type: textarea
45
+ id: misc
46
+ attributes:
47
+ label: Additional context
48
+ description: Add any other context or screenshots about the feature request here.
extensions/openOutpaint-webUI-extension/app/.github/workflows/autoformat.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Prettier Autoformatting
2
+ on:
3
+ push:
4
+ branches:
5
+ - "main"
6
+ - "testing"
7
+ pull_request:
8
+ branches: [main, testing]
9
+ types: [opened, synchronize, closed]
10
+
11
+ jobs:
12
+ prettier:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v3
17
+ with:
18
+ ref: ${{ github.event.pull_request.head.sha }}
19
+ - name: Prettify
20
+ uses: creyD/[email protected]
21
+ with:
22
+ prettier_options: --write **/*.{js,html,css,md}
extensions/openOutpaint-webUI-extension/app/.github/workflows/cachebusting.yml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Cache Busting
2
+ on:
3
+ push:
4
+ branches:
5
+ - "main"
6
+ - "testing"
7
+ pull_request:
8
+ branches: [main, testing]
9
+ types: [opened, synchronize, closed]
10
+
11
+ jobs:
12
+ update_hashes:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v3
17
+ with:
18
+ ref: ${{ github.event.pull_request.head.ref }}
19
+ - name: Update hashes in html files
20
+ run: bash .devtools/updatehashes.sh
21
+ - name: Commit
22
+ uses: EndBug/[email protected]
23
+ with:
24
+ committer_name: Github Actions
25
+ committer_email: [email protected]
26
+ message: "Fixed resource hashes"
extensions/openOutpaint-webUI-extension/app/.gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .vscode/*
2
+
3
+ # Key for embedding
4
+ key.json
5
+
6
+ # NPM things
7
+ package.json
8
+ package-lock.json
9
+ node_modules/
10
+
11
+ # Yarn things
12
+ yarn.lock
extensions/openOutpaint-webUI-extension/app/.prettierrc.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "arrowParens": "always",
3
+ "bracketSameLine": true,
4
+ "bracketSpacing": false,
5
+ "embeddedLanguageFormatting": "auto",
6
+ "htmlWhitespaceSensitivity": "ignore",
7
+ "insertPragma": false,
8
+ "jsxSingleQuote": false,
9
+ "printWidth": 80,
10
+ "proseWrap": "preserve",
11
+ "quoteProps": "as-needed",
12
+ "requirePragma": false,
13
+ "semi": true,
14
+ "singleQuote": false,
15
+ "tabWidth": 2,
16
+ "trailingComma": "es5",
17
+ "useTabs": true,
18
+ "vueIndentScriptAndStyle": false
19
+ }
extensions/openOutpaint-webUI-extension/app/CONTRIBUTING.md ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing to openOutpaint
2
+
3
+ We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
4
+
5
+ - Reporting a bug
6
+ - Discussing the current state of the code
7
+ - Submitting a fix
8
+ - Proposing new features
9
+ - Becoming a maintainer
10
+
11
+ ## We Develop with Github
12
+
13
+ We use github to host code, to track issues and feature requests, as well as accept pull requests.
14
+
15
+ ## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests
16
+
17
+ Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests:
18
+
19
+ 1. Fork the repo and create your branch from `main` or `testing`.
20
+ 2. Setup [commit hooks](https://github.com/zero01101/openOutpaint/tree/main/.devtools) for automatic calculation of cache busting hashes for resources.
21
+ 3. Please add comments when reasonable, and when possible, use [JSDoc](https://jsdoc.app/) for documenting types. Lack of this will not prevent your pull being merged, but it would be nice to have.
22
+ 4. If you've added code that should be tested please pull into `testing`. For documentation and smaller fixes, a pull request directly to `main` should be okay, unless it pertains to changes only present in `testing`.
23
+ 5. Create a pull request with a short description of what you did. Thanks for your contribution!
24
+
25
+ ## Any contributions you make will be under the MIT Software License
26
+
27
+ In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
28
+
29
+ ## Report bugs using Github's [issues](https://github.com/zero01101/openOutpaint/issues)
30
+
31
+ We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/zero01101/openOutpaint/issues); it's that easy!
32
+
33
+ ## Write bug reports with detail, background, and sample code
34
+
35
+ If possible, bug reports should have the most detail it is reasonable to have for the bug in question. If you are more versed in javascript, pointing out the issue in code, or even creating a pull request is also appreciated!
36
+
37
+ **Great Bug Reports** tend to have:
38
+
39
+ - A quick summary and/or background
40
+ - Steps to reproduce
41
+ - Be specific!
42
+ - Give sample code or screenshots if you can!
43
+ - What you expected would happen
44
+ - What actually happens
45
+ - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
46
+
47
+ We have some issue templates that are, admittedly, basically github's default templates. You can and should use that as a guide. Sometimes some fields may not be applicable to your particular report. In this case, things such as _alternative solutions_ don't need to be included.
48
+
49
+ People _love_ thorough bug reports. I'm not even kidding.
50
+
51
+ ## Use a Consistent Coding Style
52
+
53
+ For styling, we are currently using prettier for linting. And that's basically it. We are currently using tabs and some other defaults defined in the [.prettierrc.json](https://github.com/zero01101/openOutpaint/blob/main/.prettierrc.json) file. We don't use npm on our project, so you would have to install prettier and prettier-eslint locally. We have a handy [lint.sh](https://github.com/zero01101/openOutpaint/blob/main/lint.sh) script you can run, but it is recommended to use an IDE with prettier support for more practical use.
54
+
55
+ Any suggestions regarding change of styles or style guides (Airbnb, Google, or whatnot) are welcome, as the current file is quite simplistic.
56
+
57
+ ## License
58
+
59
+ By contributing, you agree that your contributions will be licensed under its MIT License.
60
+
61
+ ## References
62
+
63
+ This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/a9316a723f9e918afde44dea68b5f9f39b7d9b00/CONTRIBUTING.md) and based on [this template from briandk](https://gist.github.com/briandk/3d2e8b3ec8daf5a27a62).
extensions/openOutpaint-webUI-extension/app/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2022 tim h
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.
extensions/openOutpaint-webUI-extension/app/README.md ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # hello there 🐠
2
+
3
+ [openOutpaint creating some undersea... well, stuff](https://user-images.githubusercontent.com/1649724/205455599-7817812e-5b50-4c96-807e-268b40fa2fd7.mp4)
4
+
5
+ _silly demo example current as of [9b174d6](https://github.com/zero01101/openOutpaint/commit/9b174d66c9b9d83ce8657128c97f917b473b13a9) / v0.0.8 / 2022-12-03_ //TODO UPDATE SRSLY
6
+
7
+ this is a completely vanilla javascript and html canvas outpainting convenience doodad built for the API optionally exposed by [AUTOMATIC1111's stable diffusion webUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui), operating similarly to a few others that are probably more well-known. this simply offers an alternative for my following vain desires:
8
+
9
+ - avoiding the overhead of an additional virtual python environment or impacting a pre-existing one
10
+ - operates against the API exposed by A1111's webUI
11
+ - no external dependencies, extremely boring vanilla
12
+ - no external connectivity, self-hosted and offline
13
+ - unobfuscated (cough cough)
14
+ - <a name="terrible"></a>i am terrible at javascript and should probably correct that
15
+ - i have never used html canvas for anything before and should try it out
16
+
17
+ ## features
18
+
19
+ - SDXL "support"! (please check outpaint/inpaint fill types in the context menus and fiddle with denoising a LOT for img2img, it's touchy)
20
+ - [now available as an extension for webUI!](https://github.com/zero01101/openOutpaint-webUI-extension) you can find it under the default "available" section in the webUI _extensions_ tab
21
+ - **_NOTE: extension still requires `--api` flag in webui-user launch script_**
22
+ - intuitive, convenient outpainting - that's like the whole point right
23
+ - queueable, cancelable dreams - just start a'clickin' all over the place
24
+ - arbitrary dream reticle size - draw the rectangle of your dreams
25
+ - an [effectively infinite](https://github.com/zero01101/openOutpaint/pull/108), resizable, scalable canvas for you to paint all over
26
+ - **_NOTE: v0.0.10 introduces a new "camera control" modifier key - hold [`CTRL`] and use the scrollwheel to zoom (scroll the wheel or use the two-finger vertical gesture on, uh, modern touchpads) and pan (hold the scrollwheel button, or if you don't have one, left-click button) around the canvas_**
27
+ - extremely limited, janky support for a shockingly restrictive list of A1111 extensions including controlnet inpainting for legitimately magic promptless inpainting and outpainting ([a](https://github.com/Mikubill/sd-webui-controlnet/discussions/1464), [b](https://github.com/Mikubill/sd-webui-controlnet/discussions/1143), [c](https://github.com/Mikubill/sd-webui-controlnet/discussions/1597)) and in-line reference preprocessors for keeping existing style while replacing things (reference requires at least 2 controlnet units enabled in A1111 settings), as well as a very very basic dynamic-prompts-on-or-off toggle
28
+ - **_NOTE: this is_ JANKY, _pull requests greatly welcomed lol_**
29
+ - a very nicely functional and familiar layer system
30
+ - save, load, import, and export workspaces - includes all your layers, history, canvas size, you name it!
31
+ - inpainting/touchup mask brush
32
+ - webUI script support (but you gotta [_find it_](https://github.com/zero01101/openOutpaint/wiki/Manual))
33
+ - prompt history panel
34
+ - optional (visibly) inverted mask mode - red masks get mutated, blue masks stay the same, but you can't take both pills at once
35
+ - inpainting color brush to bring out your inner vincent van bob ross
36
+ - dedicated img2img tool with optional border masking for enhanced output coherence with existing subject matter
37
+ - marquee select tool to select regions and arbitrarily scale, rotate, create stamps, move chunks, peek at lower layers, do all sorts of damage
38
+ - optionally decoupled cursor size and output resolution
39
+ - interrogate tool
40
+ - floating control panel to easily change models/samplers/steps/prompts/CFG/etc options for each dream summoned from the latent void _(NOTE: model switching requires A1111 webUI to be on commit [5a6387e](https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/5a6387e189dc365c47a7979b9040d5b6fdd7ba43) or more recent)_
41
+ - floating toolbox with handy keyboard shortcuts
42
+ - optional grid snapping for precision
43
+ - optional hi-res fix for blank/txt2img dreams
44
+ - **_NOTE: as of v0.0.12.5/webUI commit [ef27a18](https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/ef27a18b6b7cb1a8eebdc9b2e88d25baf2c2414d), HRfix has been COMPLETELY reworked and no longer works remotely the same, thus openOutpaint's implementation is no longer compatible with versions of A1111 predating that. You will be alerted to the outdated webUI and the HRfix option will become limited to simply using [reticle dimensions / 2] in this event. Please see the [manual entry](https://github.com/zero01101/openOutpaint/wiki/Manual#hrfix) regarding HRfix and its available options._**
45
+ - optional overmasking for potentially better seams between outpaints - set overmask px value to 0 to disable the feature
46
+ - import arbitrary images and rotate/scale/stamp on the canvas whenever, wherever you'd like
47
+ - upscaler support for final output images
48
+ - saves your preferences/imported images to browser localstorage for maximum convenience
49
+ - reset to defaults button to unsave your preferences if things go squirrely
50
+ - floating navigable undo/redo palette with ctrl+z/y keyboard shortcuts for additional maximum convenience and desquirreliness
51
+ - optional generate-ahead function to keep crankin' out the dreams while you look through the ones that already exist
52
+ - _all this and much more for the low, low price of simply already owning an expensive GPU!_
53
+
54
+ ## operation
55
+
56
+ **_NOTE: [PLEASE SEE DOCUMENTATION REGARDING NEW HRfix FEATURES](https://github.com/zero01101/openOutpaint/wiki/Manual#hrfix) IMPLEMENTED AS OF webUI COMMIT [ef27a18](https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/ef27a18b6b7cb1a8eebdc9b2e88d25baf2c2414d)_**
57
+
58
+ ### prerequisities
59
+
60
+ you'll obviously need A1111's webUI installed before you can use this, thus you're presumed to have an operational python install up and running to boot.
61
+
62
+ A1111 webUI must be launched with the `--api` flag enabled, and the `--cors-allow-origins=` flag set with the host where openOutpaint will be running.
63
+
64
+ **_NOTE: the commandline flag `--gradio-debug` disables custom API routes and completely breaks openOutpaint. please remove it from your COMMANDLINE_ARGS before running openOutpaint._**
65
+
66
+ ### surprising incompatibilities
67
+
68
+ **_COLAB USERS: you may experience issues installing openOutpaint (and other webUI extensions) - there is a workaround that has been discovered and tested against [TheLastBen's fast-stable-diffusion](https://github.com/TheLastBen/fast-stable-diffusion). Please see [this discussion](https://github.com/TheLastBen/fast-stable-diffusion/discussions/1161) containing the workaround, which requires adding a command into the final cell of the colab, as well as setting `Enable_API` to `True`._**
69
+
70
+ If anything goes wrong with openOutpaint, try running it on another browser and disable all extensions and try again. If a new incompatible extension is found, please open an issue so we can notify other users of extension incompatibilities.
71
+
72
+ - [microsoft editor extension for chrome/edge seems to disable the overmask slider](https://github.com/zero01101/openOutpaint/discussions/88#discussioncomment-4498341)
73
+ - ~~[duckduckgo privacy extension for firefox breaks outpainting, resulting in pure black output](https://github.com/zero01101/openOutpaint-webUI-extension/issues/3#issuecomment-1367694000) - add an exception for your openOutpaint host (likely localhost or 127.0.0.1)~~ should be fixed as of [b128943](https://github.com/zero01101/openOutpaint/commit/b128943f0c94970600fdc1c98bfec22de619866f)
74
+ - ~~[same for dark reader](https://github.com/zero01101/openOutpaint-webUI-extension/issues/3#issuecomment-1367838766)~~ same for dark reader
75
+
76
+ ### quickstart speedrun
77
+
78
+ 1. edit your `cors-allow-origins` to include https://zero01101.github.io and run webUI
79
+ 2. go to https://zero01101.github.io/openOutpaint/ and fill in the host value with your webUI API address
80
+ 3. click things and do stuff
81
+
82
+ ### step-by-step actually useful instructions
83
+
84
+ please see the [quickstart wiki article](https://github.com/zero01101/openOutpaint/wiki/SBS-Guided-Example) and comprehensive [manual](https://github.com/zero01101/openOutpaint/wiki/Manual).
85
+
86
+ ## pull requests/bug reports
87
+
88
+ please do! see [contributing](https://github.com/zero01101/openOutpaint/blob/main/CONTRIBUTING.md) for details!
89
+
90
+ ## warranty
91
+
92
+ [lmao](https://github.com/moyix/fauxpilot#support-and-warranty)
extensions/openOutpaint-webUI-extension/app/css/colors.css ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --c-primary: #2c3333;
3
+ --c-disabled: rgb(81, 81, 81);
4
+ --c-hover: hsl(180, 7%, 30%);
5
+ --c-active: hsl(180, 7%, 25%);
6
+ --c-primary-accent: hsl(180, 7%, 40%);
7
+ --c-secondary: #395b64;
8
+ --c-accent: #a5c9ca;
9
+ --c-text: #e7f6f2;
10
+ }
extensions/openOutpaint-webUI-extension/app/css/fonts.css ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ @font-face {
2
+ font-family: "Open Sans", sans-serif;
3
+ src: url("../res/fonts/OpenSans.ttf") format("truetype");
4
+ }
extensions/openOutpaint-webUI-extension/app/css/icons.css ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .ui.inline-icon {
2
+ position: relative;
3
+
4
+ display: flex;
5
+ }
6
+
7
+ .ui.inline-icon::after {
8
+ content: "";
9
+ display: block;
10
+
11
+ position: absolute;
12
+
13
+ box-sizing: border-box;
14
+
15
+ margin: auto;
16
+ top: 15%;
17
+ bottom: 15%;
18
+
19
+ mask-size: contain;
20
+ -webkit-mask-size: contain;
21
+ mask-repeat: no-repeat;
22
+ -webkit-mask-repeat: no-repeat;
23
+
24
+ max-height: 70%;
25
+ aspect-ratio: 1;
26
+
27
+ left: 0;
28
+ right: 0;
29
+
30
+ background-color: var(--c-text);
31
+ }
32
+
33
+ .ui.inline-icon.icon-eye-off::after,
34
+ .ui.icon > .icon-eye-off {
35
+ -webkit-mask-image: url("../res/icons/eye-off.svg");
36
+ mask-image: url("../res/icons/eye-off.svg");
37
+ }
38
+
39
+ .ui.icon > .icon-eye {
40
+ -webkit-mask-image: url("../res/icons/eye.svg");
41
+ mask-image: url("../res/icons/eye.svg");
42
+ }
43
+
44
+ .ui.icon > .icon-file-plus {
45
+ -webkit-mask-image: url("../res/icons/file-plus.svg");
46
+ mask-image: url("../res/icons/file-plus.svg");
47
+ }
48
+
49
+ .ui.inline-icon.icon-flip-horizontal::after,
50
+ .ui.icon > .icon-flip-horizontal {
51
+ -webkit-mask-image: url("../res/icons/flip-horizontal.svg");
52
+ mask-image: url("../res/icons/flip-horizontal.svg");
53
+ }
54
+
55
+ .ui.inline-icon.icon-flip-vertical::after,
56
+ .ui.icon > .icon-flip-vertical {
57
+ -webkit-mask-image: url("../res/icons/flip-vertical.svg");
58
+ mask-image: url("../res/icons/flip-vertical.svg");
59
+ }
60
+
61
+ .ui.icon > .icon-file-x {
62
+ -webkit-mask-image: url("../res/icons/file-x.svg");
63
+ mask-image: url("../res/icons/file-x.svg");
64
+ }
65
+
66
+ .ui.icon > .icon-chevron-down {
67
+ -webkit-mask-image: url("../res/icons/chevron-down.svg");
68
+ mask-image: url("../res/icons/chevron-down.svg");
69
+ }
70
+
71
+ .ui.icon > .icon-chevron-up {
72
+ -webkit-mask-image: url("../res/icons/chevron-up.svg");
73
+ mask-image: url("../res/icons/chevron-up.svg");
74
+ }
75
+ .ui.icon > .icon-chevron-first {
76
+ -webkit-mask-image: url("../res/icons/chevron-first.svg");
77
+ mask-image: url("../res/icons/chevron-first.svg");
78
+ }
79
+
80
+ .ui.icon > .icon-chevron-flat-down {
81
+ -webkit-mask-image: url("../res/icons/chevron-first.svg");
82
+ mask-image: url("../res/icons/chevron-first.svg");
83
+ transform: rotate(-90deg);
84
+ }
85
+
86
+ .ui.icon > .icon-scroll {
87
+ -webkit-mask-image: url("../res/icons/scroll.svg");
88
+ mask-image: url("../res/icons/scroll.svg");
89
+ }
90
+
91
+ .ui.icon > .icon-settings {
92
+ -webkit-mask-image: url("../res/icons/settings.svg");
93
+ mask-image: url("../res/icons/settings.svg");
94
+ }
95
+
96
+ .ui.icon > .icon-unzoom {
97
+ -webkit-mask-image: url("../res/icons/scaling.svg");
98
+ mask-image: url("../res/icons/scaling.svg");
99
+ }
100
+
101
+ .ui.inline-icon.icon-grid::after,
102
+ .ui.icon > .icon-grid {
103
+ -webkit-mask-image: url("../res/icons/grid.svg");
104
+ mask-image: url("../res/icons/grid.svg");
105
+ }
106
+
107
+ .ui.inline-icon.icon-venetian-mask::after,
108
+ .ui.icon > .icon-venetian-mask {
109
+ -webkit-mask-image: url("../res/icons/venetian-mask.svg");
110
+ mask-image: url("../res/icons/venetian-mask.svg");
111
+ }
112
+
113
+ .ui.inline-icon.icon-brush::after,
114
+ .ui.icon > .icon-brush {
115
+ -webkit-mask-image: url("../res/icons/brush.svg");
116
+ mask-image: url("../res/icons/brush.svg");
117
+ }
118
+
119
+ .ui.inline-icon.icon-paintbrush::after,
120
+ .ui.icon > .icon-paintbrush {
121
+ -webkit-mask-image: url("../res/icons/paintbrush.svg");
122
+ mask-image: url("../res/icons/paintbrush.svg");
123
+ }
124
+
125
+ .ui.inline-icon.icon-slice::after,
126
+ .ui.icon > .icon-slice {
127
+ -webkit-mask-image: url("../res/icons/slice.svg");
128
+ mask-image: url("../res/icons/slice.svg");
129
+ }
130
+
131
+ .ui.inline-icon.icon-joystick::after,
132
+ .ui.icon > .icon-joystick {
133
+ -webkit-mask-image: url("../res/icons/joystick.svg");
134
+ mask-image: url("../res/icons/joystick.svg");
135
+ }
136
+
137
+ .ui.inline-icon.icon-save::after,
138
+ .ui.icon > .icon-save {
139
+ -webkit-mask-image: url("../res/icons/save.svg");
140
+ mask-image: url("../res/icons/save.svg");
141
+ }
142
+
143
+ .ui.inline-icon.icon-pencil::after,
144
+ .ui.icon > .icon-pencil {
145
+ -webkit-mask-image: url("../res/icons/pencil.svg");
146
+ mask-image: url("../res/icons/pencil.svg");
147
+ }
148
+
149
+ .ui.inline-icon.icon-download::after,
150
+ .ui.icon > .icon-download {
151
+ -webkit-mask-image: url("../res/icons/download.svg");
152
+ mask-image: url("../res/icons/download.svg");
153
+ }
154
+ .ui.inline-icon.icon-upload::after,
155
+ .ui.icon > .icon-upload {
156
+ -webkit-mask-image: url("../res/icons/upload.svg");
157
+ mask-image: url("../res/icons/upload.svg");
158
+ }
159
+ .ui.inline-icon.icon-more-horizontal::after,
160
+ .ui.icon > .icon-more-horizontal {
161
+ -webkit-mask-image: url("../res/icons/more-horizontal.svg");
162
+ mask-image: url("../res/icons/more-horizontal.svg");
163
+ }
164
+ .ui.inline-icon.icon-trash::after,
165
+ .ui.icon > .icon-trash {
166
+ -webkit-mask-image: url("../res/icons/trash.svg");
167
+ mask-image: url("../res/icons/trash.svg");
168
+ }
169
+
170
+ .ui.inline-icon.icon-expand::after,
171
+ .ui.icon > .icon-expand {
172
+ -webkit-mask-image: url("../res/icons/expand.svg");
173
+ mask-image: url("../res/icons/expand.svg");
174
+ }
175
+
176
+ .ui.inline-icon.icon-pin::after,
177
+ .ui.icon > .icon-pin {
178
+ -webkit-mask-image: url("../res/icons/pin.svg");
179
+ mask-image: url("../res/icons/pin.svg");
180
+ }
181
+
182
+ .ui.inline-icon.icon-box-select::after,
183
+ .ui.icon > .icon-box-select {
184
+ -webkit-mask-image: url("../res/icons/box-select.svg");
185
+ mask-image: url("../res/icons/box-select.svg");
186
+ }
187
+
188
+ .ui.inline-icon.icon-maximize::after,
189
+ .ui.icon > .icon-maximize {
190
+ -webkit-mask-image: url("../res/icons/maximize.svg");
191
+ mask-image: url("../res/icons/maximize.svg");
192
+ }
193
+
194
+ .ui.inline-icon.icon-clipboard-list::after,
195
+ .ui.icon > .icon-clipboard-list {
196
+ -webkit-mask-image: url("../res/icons/clipboard-list.svg");
197
+ mask-image: url("../res/icons/clipboard-list.svg");
198
+ }
extensions/openOutpaint-webUI-extension/app/css/index.css ADDED
@@ -0,0 +1,678 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * {
2
+ font-size: 100%;
3
+ font-family: Arial, Helvetica, sans-serif;
4
+ user-select: none;
5
+ }
6
+
7
+ input,
8
+ textarea {
9
+ user-select: auto;
10
+ }
11
+
12
+ /* Body is stuck with no scroll */
13
+ body {
14
+ width: 100%;
15
+ height: 100%;
16
+
17
+ margin: 0px;
18
+ padding: 0px;
19
+
20
+ overflow: clip;
21
+ }
22
+
23
+ .invisible {
24
+ display: none !important;
25
+ }
26
+
27
+ .collapsible {
28
+ background-color: rgb(0, 0, 0);
29
+ color: rgb(255, 255, 255);
30
+ border-radius: 5px;
31
+ cursor: pointer;
32
+ width: 100%;
33
+ border: none;
34
+ text-align: center;
35
+ outline: none;
36
+ padding: 0px;
37
+ }
38
+
39
+ .collapsible {
40
+ background-color: var(--c-primary);
41
+
42
+ margin-bottom: 2px;
43
+ margin-top: 5px;
44
+
45
+ transition-duration: 50ms;
46
+ }
47
+
48
+ .collapsible::before {
49
+ content: "";
50
+ display: block;
51
+
52
+ position: absolute;
53
+
54
+ width: 21px;
55
+ height: 21px;
56
+
57
+ background-color: var(--c-text);
58
+ mask-image: url("../res/icons/chevron-up.svg");
59
+ -webkit-mask-image: url("../res/icons/chevron-up.svg");
60
+ mask-size: contain;
61
+ -webkit-mask-size: contain;
62
+ rotate: 90deg;
63
+ }
64
+
65
+ .collapsible.active::before {
66
+ rotate: 180deg;
67
+ }
68
+
69
+ .display-none {
70
+ display: none;
71
+ }
72
+
73
+ .collapsible:hover {
74
+ background-color: var(--c-hover);
75
+ }
76
+
77
+ .collapsible:active {
78
+ filter: brightness(110%);
79
+ }
80
+
81
+ .content {
82
+ max-height: 0;
83
+ overflow-y: clip;
84
+ overflow-x: visible;
85
+ transition:
86
+ max-height 0.2s ease-out,
87
+ height 0s ease-out;
88
+ }
89
+
90
+ .menu-container {
91
+ background-color: rgba(255, 255, 255, 0.5);
92
+ padding-left: 10px;
93
+ padding-right: 10px;
94
+ padding-top: 5px;
95
+ padding-bottom: 5px;
96
+
97
+ color: black;
98
+ border: solid;
99
+ border-top: none;
100
+ border-color: black;
101
+ font-size: medium;
102
+ text-align: left;
103
+ max-height: fit-content;
104
+ overflow: visible;
105
+ cursor: auto;
106
+ }
107
+
108
+ #page-overlay-wrapper {
109
+ position: fixed;
110
+
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+
115
+ top: 0;
116
+ left: 0;
117
+ bottom: 0;
118
+ right: 0;
119
+
120
+ background-color: #fff6;
121
+ backdrop-filter: blur(5px);
122
+
123
+ transition-duration: 50ms;
124
+
125
+ z-index: 1000;
126
+ }
127
+
128
+ .page-overlay-window {
129
+ display: flex;
130
+ flex-direction: column;
131
+ align-items: stretch;
132
+
133
+ border-radius: 10px;
134
+
135
+ min-width: 400px;
136
+ width: 400px;
137
+ min-height: 260px;
138
+ height: 260px;
139
+
140
+ color: var(--c-text);
141
+
142
+ overflow: hidden;
143
+
144
+ position: absolute;
145
+
146
+ margin: auto;
147
+
148
+ background-color: var(--c-primary);
149
+ }
150
+
151
+ .page-overlay-window .close {
152
+ position: absolute;
153
+
154
+ cursor: pointer;
155
+
156
+ top: 0;
157
+ right: 0;
158
+
159
+ margin: 5px;
160
+
161
+ width: 25px;
162
+ height: 25px;
163
+
164
+ -webkit-mask-image: url("../res/icons/x.svg");
165
+ mask-image: url("../res/icons/x.svg");
166
+
167
+ background-color: var(--c-text);
168
+ }
169
+
170
+ .page-overlay-window .close:hover {
171
+ transform: scale(1.1);
172
+ }
173
+
174
+ .page-overlay-window .title {
175
+ padding: 10px;
176
+ padding-top: 7px;
177
+
178
+ font-size: large;
179
+ font-weight: bold;
180
+
181
+ margin: auto;
182
+
183
+ background-color: var(--c-primary);
184
+ }
185
+
186
+ #page-overlay {
187
+ border: 0;
188
+
189
+ min-height: 200px;
190
+ max-height: 600px;
191
+
192
+ width: 100%;
193
+ height: 100%;
194
+ }
195
+
196
+ /* Mask colors for mask inversion */
197
+ /* Filters are some magic acquired at https://codepen.io/sosuke/pen/Pjoqqp */
198
+ .mask-canvas {
199
+ opacity: 0%;
200
+ }
201
+
202
+ .mask-canvas.display {
203
+ opacity: 40%;
204
+ filter: invert(100%);
205
+ }
206
+
207
+ .mask-canvas.display.opaque {
208
+ opacity: 100%;
209
+ }
210
+
211
+ .mask-canvas.display.clear {
212
+ filter: invert(71%) sepia(46%) saturate(6615%) hue-rotate(321deg)
213
+ brightness(106%) contrast(100%);
214
+ }
215
+
216
+ .mask-canvas.display.hold {
217
+ filter: invert(41%) sepia(16%) saturate(5181%) hue-rotate(218deg)
218
+ brightness(103%) contrast(108%);
219
+ }
220
+
221
+ .wideSelect {
222
+ width: 100%;
223
+ text-overflow: ellipsis;
224
+ }
225
+
226
+ /* Host input */
227
+ .host-field-wrapper {
228
+ position: relative;
229
+ display: flex;
230
+
231
+ align-items: stretch;
232
+ justify-content: space-between;
233
+
234
+ width: 100%;
235
+ }
236
+
237
+ .host-field-wrapper > .host-field {
238
+ display: flex;
239
+ width: calc(100% - 15px);
240
+ }
241
+
242
+ .host-field-wrapper > .host-field > .label {
243
+ padding-left: 5px;
244
+ padding-right: 5px;
245
+
246
+ border-top-left-radius: 5px;
247
+ border-bottom-left-radius: 5px;
248
+
249
+ background-color: var(--c-primary);
250
+ color: var(--c-text);
251
+ }
252
+
253
+ .host-field-wrapper input {
254
+ display: block;
255
+ min-width: 0;
256
+
257
+ border: 0;
258
+ }
259
+
260
+ .host-field-wrapper .connection-status {
261
+ width: 15px;
262
+
263
+ position: absolute;
264
+ left: calc(100% - 15px);
265
+
266
+ border-top-right-radius: 5px;
267
+ border-bottom-right-radius: 5px;
268
+
269
+ box-sizing: inherit;
270
+
271
+ cursor: pointer;
272
+
273
+ transition-duration: 50ms;
274
+
275
+ padding-top: 1px;
276
+ padding-bottom: 1px;
277
+
278
+ overflow: hidden;
279
+ }
280
+ .host-field-wrapper .connection-status:active,
281
+ .host-field-wrapper .connection-status:hover {
282
+ width: fit-content;
283
+ padding-left: 5px;
284
+ padding-right: 6px;
285
+
286
+ filter: brightness(110%);
287
+ }
288
+
289
+ .host-field-wrapper .connection-status:active {
290
+ filter: brightness(80%);
291
+ }
292
+
293
+ .host-field-wrapper .connection-status > #connection-status-indicator-text {
294
+ opacity: 0%;
295
+ transition-duration: 20ms;
296
+ }
297
+
298
+ .host-field-wrapper
299
+ .connection-status:hover
300
+ > #connection-status-indicator-text {
301
+ opacity: 100%;
302
+ }
303
+
304
+ .host-field-wrapper .connection-status.online {
305
+ background-color: #49dd49;
306
+ color: #1f3f1f;
307
+ }
308
+
309
+ .host-field-wrapper .connection-status.offline {
310
+ background-color: #dd4949;
311
+ color: #3f1f1f;
312
+ }
313
+
314
+ .host-field-wrapper .connection-status.webui-issue {
315
+ background-color: #dddd49;
316
+ color: #3f3f1f;
317
+ }
318
+
319
+ .host-field-wrapper .connection-status.before {
320
+ background-color: #777;
321
+ color: #1f1f1f;
322
+ }
323
+
324
+ input#host {
325
+ box-sizing: border-box;
326
+ }
327
+
328
+ /* Model Select */
329
+ #models-ac-select option {
330
+ background-color: #fcc;
331
+ }
332
+
333
+ #models-ac-select option.inpainting {
334
+ background-color: #cfc;
335
+ }
336
+
337
+ /* Settings button */
338
+ .ui.icon.header-button {
339
+ padding: 0;
340
+ border: 0;
341
+
342
+ cursor: pointer;
343
+
344
+ background-color: transparent;
345
+ }
346
+
347
+ .ui.icon.header-button > *:first-child {
348
+ background-color: black;
349
+
350
+ -webkit-mask-size: contain;
351
+ mask-size: contain;
352
+
353
+ width: 28px;
354
+ height: 28px;
355
+ transition-duration: 30ms;
356
+ }
357
+
358
+ .ui.icon.header-button:hover > *:last-child {
359
+ transform: scale(1.1);
360
+ }
361
+
362
+ /* Prompt Fields */
363
+
364
+ .content.prompt {
365
+ display: flex;
366
+ align-items: stretch;
367
+ }
368
+
369
+ .content.prompt > .inputs {
370
+ width: 200px;
371
+ }
372
+
373
+ div.prompt-wrapper {
374
+ display: flex;
375
+
376
+ width: calc(100%);
377
+
378
+ overflow: visible;
379
+ }
380
+
381
+ div.prompt-wrapper > * {
382
+ flex-shrink: 0;
383
+ }
384
+
385
+ div.prompt-wrapper textarea {
386
+ margin: 0;
387
+
388
+ border-radius: 0;
389
+
390
+ border: none;
391
+
392
+ z-index: 1;
393
+ }
394
+
395
+ div.prompt-wrapper:not(:first-child) textarea {
396
+ border-top: 1px solid black;
397
+ }
398
+
399
+ div.prompt-wrapper > textarea {
400
+ box-sizing: border-box;
401
+ width: calc(100% - 20px);
402
+
403
+ padding: 2px;
404
+
405
+ transition-duration: 200ms;
406
+
407
+ resize: vertical;
408
+ }
409
+
410
+ div.prompt-wrapper > textarea:focus {
411
+ width: 700px;
412
+ }
413
+
414
+ div.prompt-wrapper > .prompt-indicator {
415
+ display: flex;
416
+
417
+ cursor: help;
418
+
419
+ width: 20px;
420
+ }
421
+
422
+ div.prompt-wrapper:first-child > .prompt-indicator {
423
+ border-top-left-radius: 5px;
424
+ }
425
+
426
+ div.prompt-wrapper:last-child > .prompt-indicator {
427
+ border-bottom-left-radius: 5px;
428
+ }
429
+
430
+ div.prompt-wrapper > .prompt-indicator.positive {
431
+ background-color: #484;
432
+ }
433
+
434
+ div.prompt-wrapper > .prompt-indicator.negative {
435
+ background-color: #844;
436
+ }
437
+ div.prompt-wrapper > .prompt-indicator.styles {
438
+ background-color: #448;
439
+ }
440
+
441
+ div.prompt-wrapper > .prompt-indicator::after {
442
+ content: "";
443
+ display: block;
444
+ margin: auto;
445
+
446
+ width: 16px;
447
+ height: 16px;
448
+
449
+ background-color: var(--c-text);
450
+
451
+ mask-size: contain;
452
+ -webkit-mask-size: contain;
453
+ }
454
+
455
+ div.prompt-wrapper > .prompt-indicator.positive::after {
456
+ mask-image: url("../res/icons/plus-square.svg");
457
+ -webkit-mask-image: url("../res/icons/plus-square.svg");
458
+ }
459
+
460
+ div.prompt-wrapper > .prompt-indicator.negative::after {
461
+ mask-image: url("../res/icons/minus-square.svg");
462
+ -webkit-mask-image: url("../res/icons/minus-square.svg");
463
+ }
464
+
465
+ div.prompt-wrapper > .prompt-indicator.styles::after {
466
+ mask-image: url("../res/icons/library.svg");
467
+ -webkit-mask-image: url("../res/icons/library.svg");
468
+ }
469
+
470
+ .prompt-history-wrapper {
471
+ position: relative;
472
+
473
+ flex-shrink: 0;
474
+
475
+ width: 20px;
476
+ }
477
+
478
+ .prompt-history-container {
479
+ display: flex;
480
+
481
+ position: absolute;
482
+
483
+ top: 0;
484
+ left: 0;
485
+
486
+ height: 100%;
487
+ }
488
+
489
+ #prompt-history {
490
+ width: 0px;
491
+ height: 100%;
492
+
493
+ transition-duration: 200ms;
494
+
495
+ background-color: #1e1e50;
496
+ }
497
+
498
+ #prompt-history.expanded {
499
+ width: 300px;
500
+ overflow-y: auto;
501
+ }
502
+
503
+ #prompt-history .entry {
504
+ display: flex;
505
+ align-items: stretch;
506
+ justify-content: stretch;
507
+
508
+ border: 1px #fff3;
509
+
510
+ height: 25px;
511
+ }
512
+
513
+ #prompt-history.expanded .entry > button {
514
+ padding: 2px;
515
+ padding-left: 5px;
516
+ }
517
+
518
+ #prompt-history .entry > button {
519
+ flex: 1;
520
+
521
+ cursor: pointer;
522
+
523
+ margin: 0;
524
+ border: 0;
525
+ padding: 0;
526
+
527
+ color: var(--c-text);
528
+
529
+ overflow: hidden;
530
+ text-overflow: ellipsis;
531
+ white-space: nowrap;
532
+
533
+ transition-duration: 100ms;
534
+ }
535
+
536
+ #prompt-history .entry:hover > button:not(:hover) {
537
+ flex-grow: 0;
538
+ flex-shrink: 1;
539
+ flex-basis: 20%;
540
+ width: 20%;
541
+ }
542
+
543
+ #prompt-history .entry > button.prompt {
544
+ background-color: #484;
545
+ }
546
+
547
+ #prompt-history .entry > button.negative {
548
+ background-color: #844;
549
+ }
550
+
551
+ #prompt-history .entry > button.styles {
552
+ background-color: #448;
553
+ }
554
+
555
+ #prompt-history .entry > button:hover {
556
+ filter: brightness(115%);
557
+ backdrop-filter: brightness(115%);
558
+ }
559
+
560
+ #prompt-history .entry > button:active {
561
+ filter: brightness(150%);
562
+ backdrop-filter: brightness(150%);
563
+ }
564
+
565
+ button.prompt-history-btn {
566
+ cursor: pointer;
567
+
568
+ border-radius: 0;
569
+
570
+ border-top-right-radius: 5px;
571
+ border-bottom-right-radius: 5px;
572
+
573
+ background-color: #1e1e50;
574
+
575
+ margin: 0;
576
+ padding: 0;
577
+ border: 0;
578
+
579
+ width: 20px;
580
+ }
581
+
582
+ button.prompt-history-btn::after {
583
+ content: "";
584
+ display: block;
585
+ margin: auto;
586
+
587
+ width: 16px;
588
+ height: 16px;
589
+
590
+ background-color: var(--c-text);
591
+
592
+ mask-size: contain;
593
+ -webkit-mask-size: contain;
594
+
595
+ mask-image: url("../res/icons/history.svg");
596
+ -webkit-mask-image: url("../res/icons/history.svg");
597
+ }
598
+
599
+ button.prompt-history-btn:hover {
600
+ filter: brightness(115%);
601
+ }
602
+
603
+ button.prompt-history-btn:active {
604
+ filter: brightness(150%);
605
+ }
606
+
607
+ /* Style Field */
608
+ select > .style-select-option {
609
+ position: relative;
610
+
611
+ cursor: pointer;
612
+ }
613
+
614
+ select > .style-select-option:hover {
615
+ background-color: #999;
616
+ }
617
+
618
+ select > .style-select-option:active {
619
+ background-color: #aaa;
620
+ }
621
+
622
+ /* Tool buttons */
623
+ .button-array {
624
+ display: flex;
625
+ justify-content: stretch;
626
+ }
627
+
628
+ .button-array > .button.tool {
629
+ flex: 1;
630
+ border-radius: 0;
631
+ }
632
+
633
+ .button-array > .button.tool:first-child {
634
+ border-top-left-radius: 5px;
635
+ border-bottom-left-radius: 5px;
636
+ }
637
+
638
+ .button-array > .button.tool:last-child {
639
+ border-top-right-radius: 5px;
640
+ border-bottom-right-radius: 5px;
641
+ }
642
+
643
+ .button.tool {
644
+ background-color: rgb(0, 0, 50);
645
+ color: rgb(255, 255, 255);
646
+ cursor: pointer;
647
+ border: none;
648
+ text-align: center;
649
+ outline: none;
650
+ font-size: 15px;
651
+ padding: 5px;
652
+ margin-top: 5px;
653
+ margin-bottom: 5px;
654
+ }
655
+
656
+ .button.tool:disabled {
657
+ background-color: #666 !important;
658
+ cursor: default;
659
+ }
660
+
661
+ .button.tool:hover {
662
+ background-color: rgb(30, 30, 80);
663
+ }
664
+ .button.tool:active,
665
+ .button.tool.active {
666
+ background-color: rgb(60, 60, 130);
667
+ }
668
+
669
+ /* Miscellaneous garbage */
670
+
671
+ .thirdwidth {
672
+ max-width: 33%;
673
+ }
674
+
675
+ .refreshbutton {
676
+ max-width: 50%;
677
+ max-height: 50%;
678
+ }
extensions/openOutpaint-webUI-extension/app/css/layers.css ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Debug floating window */
2
+ #layer-preview .preview-canvas {
3
+ background-color: white;
4
+ width: 100%;
5
+ height: 150px;
6
+ }
7
+
8
+ #layer-manager .menu-container {
9
+ height: 200px;
10
+ }
11
+
12
+ .layer-render-target {
13
+ position: fixed;
14
+ background-color: #466;
15
+
16
+ margin: 0;
17
+ padding: 0;
18
+
19
+ top: 0;
20
+ left: 0;
21
+
22
+ width: 100%;
23
+ height: 100%;
24
+ }
25
+
26
+ .layer-render-target .collection {
27
+ position: absolute;
28
+ transform-origin: 0px 0px;
29
+ }
30
+
31
+ .layer-render-target .collection > .collection-input-overlay {
32
+ position: absolute;
33
+
34
+ top: 0;
35
+ left: 0;
36
+
37
+ z-index: 10;
38
+ }
39
+
40
+ .layer-render-target canvas {
41
+ position: absolute;
42
+
43
+ top: 0;
44
+ left: 0;
45
+ bottom: 0;
46
+ right: 0;
47
+ }
48
+
49
+ .overlay-canvas {
50
+ position: fixed;
51
+
52
+ top: 0;
53
+ left: 0;
54
+
55
+ width: 100%;
56
+ height: 100%;
57
+
58
+ pointer-events: none;
59
+
60
+ z-index: 15;
61
+ }
62
+
63
+ #layer-render.pixelated canvas {
64
+ image-rendering: pixelated;
65
+ image-rendering: crisp-edges;
66
+ }
67
+
68
+ canvas.pixelated {
69
+ image-rendering: pixelated;
70
+ image-rendering: crisp-edges;
71
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/generic.css ADDED
@@ -0,0 +1,451 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* UI Floating Windows */
2
+ .floating-window {
3
+ position: fixed;
4
+ width: 250px;
5
+ height: auto;
6
+ z-index: 999;
7
+ }
8
+
9
+ .floating-window-title {
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+
14
+ cursor: move;
15
+ background-color: rgba(104, 104, 104, 0.75);
16
+
17
+ user-select: none;
18
+
19
+ padding: 5px;
20
+ padding-left: 10px;
21
+
22
+ margin-bottom: auto;
23
+ font-size: 1.5em;
24
+ color: black;
25
+ text-align: center;
26
+ border-top-left-radius: 10px;
27
+ border-top-right-radius: 10px;
28
+ border: solid;
29
+ border-bottom: none;
30
+ border-color: black;
31
+ }
32
+
33
+ .draggable {
34
+ cursor: move;
35
+ }
36
+
37
+ /* Slider Input */
38
+ div.slider-wrapper {
39
+ margin: 5px;
40
+ margin-left: 0;
41
+ margin-right: 0;
42
+ }
43
+
44
+ div.slider-wrapper {
45
+ position: relative;
46
+ height: 20px;
47
+ border-radius: 5px;
48
+
49
+ overflow-y: visible;
50
+ }
51
+
52
+ div.slider-wrapper * {
53
+ height: 20px;
54
+ border-radius: 5px;
55
+ margin: 0;
56
+ }
57
+
58
+ div.slider-wrapper > * {
59
+ position: absolute;
60
+ padding: inherit;
61
+ width: 100%;
62
+
63
+ left: 0;
64
+ right: 0;
65
+ top: 0;
66
+ bottom: 0;
67
+
68
+ overflow: hidden;
69
+ }
70
+
71
+ div.slider-wrapper > div.under {
72
+ display: flex;
73
+ background-color: var(--c-primary-accent);
74
+ }
75
+ div.slider-wrapper > div.under > div:first-child {
76
+ background-color: var(--c-primary);
77
+ border-top-right-radius: 0;
78
+ border-bottom-right-radius: 0;
79
+ }
80
+ div.slider-wrapper > div.under > div:last-child {
81
+ flex: 1;
82
+ border-top-left-radius: 0;
83
+ border-bottom-left-radius: 0;
84
+ }
85
+ div.slider-wrapper > div.under > * {
86
+ height: 100%;
87
+ }
88
+
89
+ div.slider-wrapper > div.over {
90
+ cursor: pointer;
91
+ }
92
+
93
+ div.slider-wrapper > input.text {
94
+ color: var(--c-text);
95
+
96
+ flex: 1;
97
+ appearance: textfield;
98
+ border: 0px;
99
+
100
+ height: 100%;
101
+ text-align: center;
102
+ background-color: transparent;
103
+ }
104
+
105
+ /* Checkbox Input */
106
+ div.checkbox-array {
107
+ display: flex;
108
+
109
+ margin-top: 5px;
110
+ margin-bottom: 5px;
111
+ }
112
+
113
+ input.oo-checkbox[type="checkbox"] {
114
+ /* Hide original checkbox */
115
+ -webkit-appearance: none;
116
+ appearance: none;
117
+
118
+ flex: 1;
119
+
120
+ margin: 0;
121
+
122
+ min-width: 28px;
123
+ height: 28px;
124
+
125
+ background-color: var(--c-primary);
126
+
127
+ cursor: pointer;
128
+ }
129
+
130
+ input.oo-checkbox[type="checkbox"]:disabled {
131
+ background-color: #666 !important;
132
+ cursor: default !important;
133
+ }
134
+
135
+ input.oo-checkbox[type="checkbox"]:disabled:hover {
136
+ filter: none !important;
137
+ }
138
+
139
+ input.oo-checkbox[type="checkbox"]:checked::after {
140
+ background-color: #66f;
141
+ }
142
+
143
+ input.oo-checkbox[type="checkbox"]:hover {
144
+ background-color: var(--c-hover);
145
+ }
146
+
147
+ input.oo-checkbox[type="checkbox"]:active {
148
+ filter: brightness(120%);
149
+ }
150
+
151
+ input.oo-checkbox[type="checkbox"]:first-child {
152
+ border-top-left-radius: 5px;
153
+ border-bottom-left-radius: 5px;
154
+ }
155
+
156
+ input.oo-checkbox[type="checkbox"]:last-child {
157
+ border-top-right-radius: 5px;
158
+ border-bottom-right-radius: 5px;
159
+ }
160
+
161
+ /* Mask Inversion Checkbox */
162
+ input.oo-checkbox[type="checkbox"].invert-mask-checkbox::after {
163
+ background-color: var(--c-text);
164
+ }
165
+
166
+ input.oo-checkbox[type="checkbox"].invert-mask-checkbox:hover {
167
+ filter: brightness(120%);
168
+ }
169
+
170
+ input.oo-checkbox[type="checkbox"].invert-mask-checkbox:active {
171
+ filter: brightness(140%);
172
+ }
173
+
174
+ input.oo-checkbox[type="checkbox"].invert-mask-checkbox {
175
+ background-color: #922;
176
+ }
177
+
178
+ input.oo-checkbox[type="checkbox"].invert-mask-checkbox:checked {
179
+ background-color: #229;
180
+ }
181
+
182
+ /* Bare Select */
183
+
184
+ .bareselector {
185
+ border-radius: 5px;
186
+
187
+ background-color: white;
188
+
189
+ overflow-y: auto;
190
+
191
+ margin-top: 0;
192
+ margin-left: 0;
193
+
194
+ max-height: 200px;
195
+ min-width: 100%;
196
+ max-width: 800px;
197
+
198
+ width: fit-content;
199
+ z-index: 200;
200
+ }
201
+
202
+ /* Autocomplete Select */
203
+ div.autocomplete {
204
+ border-radius: 5px;
205
+ }
206
+
207
+ div.autocomplete > .autocomplete-text {
208
+ box-sizing: border-box;
209
+
210
+ border-radius: 5px;
211
+
212
+ width: 100%;
213
+ }
214
+
215
+ div.autocomplete > .refreshable {
216
+ width: 82% !important;
217
+ }
218
+
219
+ div.autocomplete > .autocomplete-list {
220
+ position: absolute;
221
+
222
+ background-color: white;
223
+
224
+ overflow-y: auto;
225
+
226
+ margin-top: 0;
227
+ margin-left: 0;
228
+
229
+ max-height: 200px;
230
+ min-width: 100%;
231
+ max-width: 800px;
232
+
233
+ width: fit-content;
234
+ z-index: 200;
235
+ }
236
+
237
+ div.autocomplete > .autocomplete-list > .autocomplete-option {
238
+ position: relative;
239
+ cursor: pointer;
240
+
241
+ overflow: hidden;
242
+ text-overflow: ellipsis;
243
+ white-space: nowrap;
244
+
245
+ padding: 3px;
246
+ }
247
+
248
+ div.autocomplete > .autocomplete-list > .autocomplete-option:hover {
249
+ background-color: #dddf;
250
+ }
251
+
252
+ div.autocomplete > .autocomplete-list > .autocomplete-option.selected::after {
253
+ content: "";
254
+
255
+ position: absolute;
256
+ right: 5px;
257
+ top: 0;
258
+
259
+ height: 100%;
260
+ aspect-ratio: 1;
261
+
262
+ background-color: darkgreen;
263
+
264
+ -webkit-mask-image: url("../../res/icons/check.svg");
265
+ -webkit-mask-size: contain;
266
+ mask-image: url("../../res/icons/check.svg");
267
+ mask-size: contain;
268
+ }
269
+
270
+ /* Select Input */
271
+ select > option:checked::after {
272
+ content: "";
273
+
274
+ position: absolute;
275
+ right: 5px;
276
+ top: 0;
277
+
278
+ height: 100%;
279
+ aspect-ratio: 1;
280
+
281
+ background-color: darkgreen;
282
+
283
+ -webkit-mask-image: url("../../res/icons/check.svg");
284
+ -webkit-mask-size: contain;
285
+ mask-image: url("../../res/icons/check.svg");
286
+ mask-size: contain;
287
+ }
288
+ /*************/
289
+ /* UI styles */
290
+ /*************/
291
+
292
+ /* The separator */
293
+ .ui.separator {
294
+ width: 80%;
295
+ margin: auto;
296
+ align-self: center;
297
+ border-top: 1px var(--c-hover) solid;
298
+ }
299
+
300
+ /* Icon button */
301
+ .ui.square {
302
+ aspect-ratio: 1;
303
+ }
304
+
305
+ .ui.button {
306
+ cursor: pointer;
307
+
308
+ padding: 0;
309
+ margin: 0;
310
+ border: 0;
311
+ color: var(--c-text);
312
+ background-color: var(--c-primary);
313
+ transition-duration: 50ms;
314
+ }
315
+
316
+ .ui.button:hover {
317
+ background-color: var(--c-hover);
318
+ }
319
+
320
+ .ui.button:active {
321
+ background-color: var(--c-hover);
322
+ filter: brightness(120%);
323
+ }
324
+
325
+ .ui.button.icon {
326
+ display: flex;
327
+ align-items: stretch;
328
+ }
329
+
330
+ .ui.button.icon > *:first-child {
331
+ flex: 1;
332
+ margin: 3px;
333
+
334
+ -webkit-mask-position: center;
335
+ mask-position: center;
336
+
337
+ -webkit-mask-size: contain;
338
+ mask-size: contain;
339
+ -webkit-mask-repeat: no-repeat;
340
+ mask-repeat: no-repeat;
341
+ background-color: var(--c-text);
342
+ }
343
+
344
+ /**
345
+ * Generic list
346
+ */
347
+
348
+ .list {
349
+ height: 200px;
350
+
351
+ overflow-y: auto;
352
+
353
+ background-color: var(--c-primary);
354
+
355
+ border-top-left-radius: 5px;
356
+ border-top-right-radius: 5px;
357
+ }
358
+
359
+ .list > *:first-child {
360
+ border-top-left-radius: 5px;
361
+ border-top-right-radius: 5px;
362
+ }
363
+
364
+ .list .list-item {
365
+ display: flex;
366
+ align-items: center;
367
+ justify-content: space-between;
368
+
369
+ height: 25px;
370
+ padding-left: 5px;
371
+ padding-right: 5px;
372
+
373
+ cursor: pointer;
374
+
375
+ color: var(--c-text);
376
+
377
+ transition-duration: 50ms;
378
+ }
379
+
380
+ .list .list-item.active {
381
+ background-color: var(--c-active);
382
+ }
383
+ .list .list-item.active:hover,
384
+ .list .list-item:hover {
385
+ background-color: var(--c-hover);
386
+ }
387
+ .list .list-item.active:active,
388
+ .list .list-item:active {
389
+ background-color: var(--c-hover);
390
+ filter: brightness(120%);
391
+ }
392
+
393
+ .list .list-item > .title {
394
+ flex: 1;
395
+ text-overflow: ellipsis;
396
+ overflow: hidden;
397
+ white-space: nowrap;
398
+
399
+ background-color: transparent;
400
+
401
+ border: 0;
402
+ color: var(--c-text);
403
+ }
404
+
405
+ .list .list-item > .actions {
406
+ display: flex;
407
+ align-self: stretch;
408
+ }
409
+
410
+ .list .actions > button {
411
+ display: flex;
412
+ align-items: stretch;
413
+
414
+ padding: 0;
415
+
416
+ width: 25px;
417
+ aspect-ratio: 1;
418
+
419
+ background-color: transparent;
420
+ border: 0;
421
+ cursor: pointer;
422
+ }
423
+
424
+ .list .list-item > .actions > *:hover > * {
425
+ margin: 2px;
426
+ }
427
+
428
+ .list .actions > button > *:first-child {
429
+ flex: 1;
430
+ margin: 3px;
431
+
432
+ -webkit-mask-size: contain;
433
+ mask-size: contain;
434
+ background-color: var(--c-text);
435
+ }
436
+
437
+ /* Generic buttons */
438
+ .list .actions > .delete-btn > *:first-child {
439
+ -webkit-mask-image: url("../../res/icons/trash.svg");
440
+ mask-image: url("../../res/icons/trash.svg");
441
+ }
442
+
443
+ .list .actions > .rename-btn > *:first-child {
444
+ -webkit-mask-image: url("../../res/icons/edit.svg");
445
+ mask-image: url("../../res/icons/edit.svg");
446
+ }
447
+
448
+ .list .actions > .download-btn > *:first-child {
449
+ -webkit-mask-image: url("../../res/icons/download.svg");
450
+ mask-image: url("../../res/icons/download.svg");
451
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/history.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #historyContainer > .info {
2
+ padding: 0;
3
+ }
4
+
5
+ #history.history {
6
+ height: 200px;
7
+ overflow-y: scroll;
8
+ overflow-x: hidden;
9
+ }
10
+
11
+ #history.history > .history-item {
12
+ cursor: pointer;
13
+
14
+ padding: 5px;
15
+ padding-top: 2px;
16
+ padding-bottom: 2px;
17
+ }
18
+
19
+ #history.history > .history-item {
20
+ background-color: #0000;
21
+ }
22
+ #history.history > .history-item:hover {
23
+ background-color: #fff5;
24
+ }
25
+
26
+ #history.history > .history-item.current {
27
+ background-color: #66f5;
28
+ }
29
+ #history.history > .history-item.current:hover {
30
+ background-color: #66f5;
31
+ }
32
+
33
+ #history.history > .history-item.future {
34
+ background-color: #4445;
35
+ }
36
+ #history.history > .history-item.future:hover {
37
+ background-color: #ddd5;
38
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/layers.css ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .layer-manager {
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: stretch;
5
+
6
+ border-radius: 5px;
7
+ overflow: hidden;
8
+
9
+ background-color: var(--c-primary);
10
+ }
11
+
12
+ #layer-list {
13
+ height: 200px;
14
+
15
+ overflow-y: auto;
16
+
17
+ background-color: var(--c-primary);
18
+
19
+ border-top-left-radius: 5px;
20
+ border-top-right-radius: 5px;
21
+ }
22
+
23
+ #layer-list > *:first-child {
24
+ border-top-left-radius: 5px;
25
+ border-top-right-radius: 5px;
26
+ }
27
+
28
+ #layer-list .ui-layer {
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: space-between;
32
+
33
+ height: 25px;
34
+ padding-left: 5px;
35
+ padding-right: 5px;
36
+
37
+ cursor: pointer;
38
+
39
+ color: var(--c-text);
40
+
41
+ transition-duration: 50ms;
42
+ }
43
+
44
+ #layer-list .ui-layer.active {
45
+ background-color: var(--c-active);
46
+ }
47
+ #layer-list .ui-layer.active:hover,
48
+ #layer-list .ui-layer:hover {
49
+ background-color: var(--c-hover);
50
+ }
51
+ #layer-list .ui-layer.active:active,
52
+ #layer-list .ui-layer:active {
53
+ background-color: var(--c-hover);
54
+ filter: brightness(120%);
55
+ }
56
+
57
+ #layer-list .ui-layer > .title {
58
+ flex: 1;
59
+ text-overflow: ellipsis;
60
+ overflow: hidden;
61
+ white-space: nowrap;
62
+
63
+ background-color: transparent;
64
+
65
+ border: 0;
66
+ color: var(--c-text);
67
+ }
68
+
69
+ #layer-list .ui-layer > .actions {
70
+ display: flex;
71
+ align-self: stretch;
72
+ }
73
+
74
+ #layer-list .actions > button {
75
+ display: flex;
76
+ align-items: stretch;
77
+
78
+ padding: 0;
79
+
80
+ width: 25px;
81
+ aspect-ratio: 1;
82
+
83
+ background-color: transparent;
84
+ border: 0;
85
+ cursor: pointer;
86
+ }
87
+
88
+ #layer-list .ui-layer > .actions > *:hover > * {
89
+ margin: 2px;
90
+ }
91
+
92
+ #layer-list .actions > button > *:first-child {
93
+ flex: 1;
94
+ margin: 3px;
95
+
96
+ -webkit-mask-size: contain;
97
+ mask-size: contain;
98
+ background-color: var(--c-text);
99
+ }
100
+
101
+ #layer-list .actions > .rename-btn > *:first-child {
102
+ -webkit-mask-image: url("../../res/icons/edit.svg");
103
+ mask-image: url("../../res/icons/edit.svg");
104
+ }
105
+
106
+ #layer-list .actions > .delete-btn > *:first-child {
107
+ -webkit-mask-image: url("../../res/icons/trash.svg");
108
+ mask-image: url("../../res/icons/trash.svg");
109
+ }
110
+
111
+ #layer-list .actions > .hide-btn > *:first-child {
112
+ -webkit-mask-image: url("../../res/icons/eye.svg");
113
+ mask-image: url("../../res/icons/eye.svg");
114
+ }
115
+ #layer-list .hidden .actions > .hide-btn > *:first-child {
116
+ -webkit-mask-image: url("../../res/icons/eye-off.svg");
117
+ mask-image: url("../../res/icons/eye-off.svg");
118
+ }
119
+
120
+ .layer-manager > .separator {
121
+ width: calc(100% - 10px);
122
+ }
123
+
124
+ .layer-manager > .layer-list-actions {
125
+ display: flex;
126
+ padding: 0;
127
+
128
+ justify-content: stretch;
129
+ }
130
+
131
+ .layer-manager > .layer-list-actions > * {
132
+ flex: 1;
133
+ height: 25px;
134
+ }
135
+
136
+ /* Resizing buttons */
137
+ .expand-button {
138
+ display: flex;
139
+
140
+ align-items: center;
141
+ justify-content: center;
142
+
143
+ margin: 0;
144
+ padding: 0;
145
+ border: 0;
146
+
147
+ background-color: transparent;
148
+
149
+ cursor: pointer;
150
+
151
+ transition-duration: 300ms;
152
+ transition-property: background-color;
153
+
154
+ border: 2px solid #293d3d30;
155
+ }
156
+
157
+ .expand-button::after {
158
+ content: "";
159
+
160
+ background-color: #293d3d77;
161
+
162
+ -webkit-mask-image: url("../../res/icons/chevron-up.svg");
163
+ mask-image: url("../../res/icons/chevron-up.svg");
164
+ -webkit-mask-size: contain;
165
+ mask-size: contain;
166
+
167
+ width: 60px;
168
+ height: 60px;
169
+ }
170
+
171
+ .expand-button:hover::after {
172
+ background-color: #466;
173
+ }
174
+
175
+ .expand-button.right::after {
176
+ transform: rotate(90deg);
177
+ }
178
+
179
+ .expand-button.bottom::after {
180
+ transform: rotate(180deg);
181
+ }
182
+
183
+ .expand-button.left::after {
184
+ transform: rotate(270deg);
185
+ }
186
+
187
+ .expand-button.left {
188
+ border-top-left-radius: 10px;
189
+ border-bottom-left-radius: 10px;
190
+ }
191
+ .expand-button.top {
192
+ border-top-left-radius: 10px;
193
+ border-top-right-radius: 10px;
194
+ }
195
+ .expand-button.right {
196
+ border-top-right-radius: 10px;
197
+ border-bottom-right-radius: 10px;
198
+ }
199
+ .expand-button.bottom {
200
+ border-bottom-right-radius: 10px;
201
+ border-bottom-left-radius: 10px;
202
+ }
203
+
204
+ .expand-button:hover {
205
+ background-color: #293d3d77;
206
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/notifications.css ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** Notification Ripple */
2
+ @keyframes notification-ripple {
3
+ 0% {
4
+ border: none 0px;
5
+ }
6
+ 50% {
7
+ border: solid 5px;
8
+ }
9
+ 100% {
10
+ border: none 0px;
11
+ }
12
+ }
13
+
14
+ div.notification-highlight {
15
+ position: fixed;
16
+ top: 0;
17
+ left: 0;
18
+
19
+ width: 100%;
20
+ height: 100%;
21
+
22
+ z-index: 1000;
23
+ pointer-events: none;
24
+
25
+ box-sizing: border-box;
26
+
27
+ animation: notification-ripple;
28
+ animation-iteration-count: 1;
29
+ }
30
+
31
+ .notification-highlight.notification-success {
32
+ border-color: #39b34999 !important;
33
+ }
34
+ .notification-highlight.notification-warn {
35
+ border-color: #b3a13999 !important;
36
+ }
37
+ .notification-highlight.notification-info {
38
+ border-color: #3976b399 !important;
39
+ }
40
+
41
+ /** Notification area */
42
+ .notification-area {
43
+ position: absolute;
44
+
45
+ width: 250px;
46
+ min-width: 200px;
47
+
48
+ z-index: 25;
49
+
50
+ pointer-events: none;
51
+
52
+ padding: 10px;
53
+ }
54
+
55
+ .notification-area > * {
56
+ pointer-events: all;
57
+ }
58
+
59
+ .notification-area.bottom-left {
60
+ left: 0px;
61
+ bottom: 0px;
62
+ }
63
+
64
+ /** Notifications */
65
+ .notification-area .notification {
66
+ position: relative;
67
+
68
+ cursor: pointer;
69
+
70
+ display: flex;
71
+ justify-content: space-between;
72
+ align-items: flex-start;
73
+
74
+ border-radius: 5px;
75
+ border: solid 1px;
76
+
77
+ padding: 5px;
78
+ margin-top: 5px;
79
+
80
+ color: white;
81
+ }
82
+
83
+ .notification-area .notification:hover {
84
+ filter: brightness(110%);
85
+ }
86
+
87
+ .notification-area .notification:active {
88
+ filter: brightness(90%);
89
+ }
90
+
91
+ .notification-area .notification-content {
92
+ overflow: hidden;
93
+ text-overflow: ellipsis;
94
+ white-space: nowrap;
95
+
96
+ max-height: 100%;
97
+ }
98
+
99
+ .notification-area .notification.expanded .notification-content {
100
+ white-space: normal !important;
101
+ }
102
+
103
+ .notification .notification-closebtn {
104
+ position: relative;
105
+
106
+ flex: 0;
107
+
108
+ cursor: pointer;
109
+
110
+ padding: 0;
111
+ border: 0;
112
+
113
+ min-width: 20px;
114
+ max-width: 20px;
115
+ min-height: 20px;
116
+ max-height: 20px;
117
+
118
+ border-radius: 10px;
119
+
120
+ background-color: #0002;
121
+
122
+ transition-duration: 20ms;
123
+ }
124
+
125
+ .notification .notification-closebtn:hover {
126
+ background-color: #fff2;
127
+ }
128
+
129
+ .notification .notification-closebtn:active {
130
+ background-color: #fff4;
131
+ }
132
+
133
+ .notification .notification-closebtn::after {
134
+ content: "";
135
+ position: absolute;
136
+
137
+ cursor: pointer;
138
+
139
+ top: 0;
140
+ right: 0;
141
+
142
+ margin: 2px;
143
+
144
+ width: 16px;
145
+ height: 16px;
146
+
147
+ -webkit-mask-size: contain;
148
+ mask-size: contain;
149
+
150
+ -webkit-mask-image: url("../../res/icons/x.svg");
151
+ mask-image: url("../../res/icons/x.svg");
152
+
153
+ background-color: var(--c-text);
154
+ }
155
+
156
+ /** Notification Types */
157
+ .notification-area .notification.info {
158
+ background-color: #3976b399;
159
+ border-color: #12375c;
160
+ }
161
+
162
+ .notification-area .notification.success {
163
+ background-color: #39b34999;
164
+ border-color: #1b5c12;
165
+ }
166
+
167
+ .notification-area .notification.error {
168
+ background-color: #b3393999;
169
+ border-color: #5c1212;
170
+ }
171
+
172
+ .notification-area .notification.warn {
173
+ background-color: #b3a13999;
174
+ border-color: #5c4e12;
175
+ }
176
+
177
+ /** Dialog */
178
+ .dialog-bg {
179
+ position: fixed;
180
+
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+
185
+ top: 0;
186
+ left: 0;
187
+ bottom: 0;
188
+ right: 0;
189
+
190
+ backdrop-filter: blur(5px);
191
+ background-color: #fff6;
192
+
193
+ z-index: 1000;
194
+ }
195
+
196
+ .dialog-bg .dialog {
197
+ background-color: var(--c-primary);
198
+ color: var(--c-text);
199
+
200
+ border-radius: 10px;
201
+
202
+ position: absolute;
203
+ margin: auto;
204
+
205
+ min-width: 200px;
206
+ min-height: 20px;
207
+
208
+ max-width: 400px;
209
+ }
210
+
211
+ .dialog .dialog-title {
212
+ margin: 10px;
213
+ font-weight: bold;
214
+ }
215
+
216
+ .dialog .dialog-content {
217
+ margin: 10px;
218
+ }
219
+
220
+ .dialog .dialog-choices {
221
+ display: flex;
222
+ }
223
+
224
+ .dialog .dialog-choices > *:first-child {
225
+ border-bottom-left-radius: 10px;
226
+ }
227
+ .dialog .dialog-choices > *:last-child {
228
+ border-bottom-right-radius: 10px;
229
+ }
230
+
231
+ .dialog .dialog-choices > * {
232
+ flex: 1;
233
+
234
+ cursor: pointer;
235
+
236
+ padding: 5px;
237
+
238
+ background-color: transparent;
239
+ color: var(--c-text);
240
+
241
+ border: 0px;
242
+ border-top: solid 1px var(--c-hover);
243
+
244
+ transition-duration: 50ms;
245
+ }
246
+
247
+ .dialog .dialog-choices > *:not(:first-child) {
248
+ border-left: solid 1px var(--c-hover);
249
+ }
250
+
251
+ .dialog .dialog-choices > *:hover {
252
+ background-color: var(--c-hover);
253
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/tool/colorbrush.css ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .brush-color-picker.wrapper {
2
+ position: relative;
3
+
4
+ height: 32px;
5
+
6
+ display: flex;
7
+ flex-direction: row;
8
+ align-items: stretch;
9
+ justify-content: space-between;
10
+ }
11
+
12
+ .brush-color-picker.picker {
13
+ cursor: pointer;
14
+
15
+ flex: 1;
16
+
17
+ height: 100%;
18
+
19
+ border-bottom-left-radius: 3px;
20
+ border-top-left-radius: 3px;
21
+
22
+ padding: 0;
23
+ border: 0;
24
+ }
25
+
26
+ .brush-color-picker.eyedropper {
27
+ cursor: pointer;
28
+
29
+ border-radius: 3px;
30
+ border-bottom-left-radius: 0;
31
+ border-top-left-radius: 0;
32
+
33
+ height: 100%;
34
+ aspect-ratio: 1;
35
+
36
+ border: 0;
37
+
38
+ background-image: url("../../../res/icons/pipette.svg");
39
+ background-repeat: no-repeat;
40
+ background-position: center;
41
+ background-size: contain;
42
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/tool/dream.css ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .dream-stop-btn {
2
+ width: 100px;
3
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/tool/stamp.css ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .resource-manager {
2
+ position: relative;
3
+ border-radius: 5px;
4
+ }
5
+
6
+ .resource-manager {
7
+ user-select: none;
8
+ }
9
+ .resource-manager > .preview-pane {
10
+ display: none;
11
+
12
+ position: absolute;
13
+
14
+ height: 200px;
15
+ width: 200px;
16
+
17
+ right: -200px;
18
+ top: 0px;
19
+
20
+ background-color: white;
21
+ background-size: contain;
22
+ background-repeat: no-repeat;
23
+ background-position: center;
24
+
25
+ border-radius: 2px;
26
+ }
27
+
28
+ .resource-manager > .resource-list {
29
+ height: 200px;
30
+
31
+ border-top-left-radius: 5px;
32
+ border-top-right-radius: 5px;
33
+
34
+ overflow-y: scroll;
35
+ overflow-x: hidden;
36
+ }
37
+
38
+ .resource-manager > .upload-button {
39
+ display: block;
40
+ width: 100%;
41
+
42
+ padding-left: 0;
43
+ padding-right: 0;
44
+
45
+ margin-top: 0;
46
+
47
+ text-align: center;
48
+
49
+ border-top-left-radius: 0px;
50
+ border-top-right-radius: 0px;
51
+
52
+ border-bottom-left-radius: 5px;
53
+ border-bottom-right-radius: 5px;
54
+
55
+ border: 0px;
56
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/toolbar.css ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ui-toolbar {
2
+ align-content: center;
3
+
4
+ width: 60px;
5
+
6
+ border-radius: 5px;
7
+
8
+ color: var(--c-text);
9
+ background-color: var(--c-primary);
10
+ }
11
+
12
+ #ui-toolbar * {
13
+ user-select: none;
14
+ }
15
+
16
+ #ui-toolbar .handle {
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+
21
+ height: 10px;
22
+ }
23
+
24
+ #ui-toolbar .handle > .line {
25
+ width: 80%;
26
+ border-top: 2px #777 dotted;
27
+ }
28
+
29
+ #ui-toolbar .tool .tool-icon {
30
+ filter: invert(60%);
31
+ }
32
+ #ui-toolbar .tool.using .tool-icon {
33
+ filter: invert(80%);
34
+ }
35
+ #ui-toolbar .tool:hover .tool-icon {
36
+ filter: invert(90%);
37
+ }
38
+
39
+ /* Toolbar lock indicator */
40
+ #ui-toolbar .lock-indicator {
41
+ position: absolute;
42
+ display: none;
43
+
44
+ padding: 0;
45
+
46
+ right: 2px;
47
+ top: 10px;
48
+
49
+ width: 15px;
50
+ height: 15px;
51
+
52
+ background-color: red;
53
+
54
+ -webkit-mask-image: url("../../res/icons/lock.svg");
55
+ -webkit-mask-size: contain;
56
+ mask-image: url("../../res/icons/lock.svg");
57
+ mask-size: contain;
58
+ }
59
+
60
+ /* The separator */
61
+ #ui-toolbar .separator {
62
+ width: 80%;
63
+ margin: auto;
64
+ align-self: center;
65
+ border-top: 1px var(--c-hover) solid;
66
+ }
67
+
68
+ /* Styles for the tool buttons */
69
+ #ui-toolbar .tool {
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+
74
+ aspect-ratio: 1;
75
+ margin: 5px;
76
+ border-radius: 5px;
77
+
78
+ cursor: pointer;
79
+
80
+ transition-duration: 50ms;
81
+ }
82
+
83
+ #ui-toolbar .tool.using {
84
+ background-color: var(--c-active);
85
+ }
86
+
87
+ #ui-toolbar .tool:hover {
88
+ background-color: var(--c-hover);
89
+ }
90
+
91
+ #ui-toolbar .tool:active {
92
+ background-color: var(--c-hover);
93
+ filter: brightness(120%);
94
+ }
extensions/openOutpaint-webUI-extension/app/css/ui/workspace.css ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #workspace-select input.autocomplete-text {
2
+ border-top-right-radius: 0;
3
+ border-bottom-right-radius: 0;
4
+
5
+ padding-left: 5px;
6
+
7
+ border: none;
8
+
9
+ text-overflow: ellipsis;
10
+ }
11
+
12
+ #workspace-select-area .buttons > *:last-child {
13
+ border-top-right-radius: 5px;
14
+ border-bottom-right-radius: 5px;
15
+ }
16
+
17
+ .workspace-btn {
18
+ cursor: pointer;
19
+
20
+ border: 0;
21
+ width: 21px;
22
+ height: 21px;
23
+
24
+ background-color: var(--c-primary);
25
+ }
26
+
27
+ .workspace-btn:disabled {
28
+ cursor: default;
29
+ background-color: var(--c-disabled) !important;
30
+ }
31
+
32
+ .workspace-btn:hover {
33
+ background-color: var(--c-hover);
34
+ }
35
+
36
+ .workspace-btn:active {
37
+ background-color: var(--c-active);
38
+ }
39
+
40
+ .workspace-collapsible {
41
+ position: relative;
42
+
43
+ width: 0;
44
+ overflow: visible;
45
+ }
46
+
47
+ .workspace-collapsible > *:first-child {
48
+ display: flex;
49
+
50
+ width: fit-content;
51
+ height: 21px;
52
+
53
+ transition-duration: 50ms;
54
+ }
55
+
56
+ .workspace-collapsible.collapsed > *:first-child {
57
+ width: 0 !important;
58
+ overflow: hidden !important;
59
+ }
extensions/openOutpaint-webUI-extension/app/defaultscripts.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "defaultScripts": {
3
+ "Loopback": {
4
+ "titleText": "IMG2IMG ONLY\n\nParams:\nloops (int) //def: 8\ndenoising_strength_change_factor (decimal, 0.90-1.10) //def: 0.99\nappend_interrogation (enum, str: [\"None\",\"CLIP\",\"DeepBooru\"]) //def: None",
5
+ "scriptValues": "[8, 0.99, \"None\"]"
6
+ },
7
+ "Prompt matrix": {
8
+ "titleText": "Params:\nput_at_start (bool): expect pipe (|) delimited options at start of prompt //def: false\ndifferent_seeds (bool): use different seeds for each picture //def: false\nprompt_type (enum, str: [\"positive\",\"negative\"]) //def: \"positive\"\nvariations_delimiter (enum, str [\"comma\", \"space\"] //def: \"comma\"\nmargin_size (int): px margin value //def: 2",
9
+ "scriptValues": "[false, false, \"positive\", \"comma\", 2]"
10
+ },
11
+ "X/Y/Z plot": {
12
+ "titleText": "Params:\nx_type (int): index of axis type (see below) //def: 3\nx_values (mixed, str) //def: \"0.00-0.99 [4]\"\nx_values_dropdown (NOIDEA) //def: \"\"\ny_type (int) //def: 4\ny_values (mixed, str) //def: \"5-30 [4]\"\ny_values_dropdown (NOIDEA) //def: \"\"\nz_type (int) //def: 6\nz_values (mixed, str) //def: \"2.5-12.5 [4]\"\nz_values_dropdown (NOIDEA) //def: \"\"\ndraw_legend (bool): return grid of all images //def: false\ninclude_lone_images (bool): return individual images //def: true\ninclude_subgrids (bool) //def: false\nno_fixed_seeds (bool): use different seeds for each picture //def: false\nmargin_size (int): grid margins in px //def: 2\n\nAvailable axis types:\n0: Nothing\n1: Seed\n2: Var. seed\n3: Var. strength\n4: Steps\n5: Hires steps (txt2img only)\n6: CFG Scale\n7: Image CFG Scale (img2img with instructPix2Pix only)\n8: Prompt S/R\n9: Prompt order\n10: Sampler (txt2img only)\n11: Sampler (img2img only)\n12: Checkpoint Name\n13: Negative Guidance minimum sigma\n14: Sigma Churn\n15: Sigma min\n16: Sigma max\n17: Sigma noise\n18: Schedule Type\n19: Schedule min sigma\n20:Schedule max sigma\n21: Schedule rho\n22: Eta\n23: Clip skip\n24: Denoising\n25: Hires upscaler (txt2img only)\n26: Cond. Image Mask Weight (img2img only)\n27: VAE\n23: Styles\n28: UniPC Order\n29: Face Restore\n30: Token merging ratio\n31: Token merging ratio hi-res",
13
+ "scriptValues": "[3, \"0.00-0.99 [4]\", \"\", 4, \"5-30 [4]\", \"\", 6, \"2.5-12.5 [4]\", \"\", false, true, false, false, 2]"
14
+ }
15
+ }
16
+ }
extensions/openOutpaint-webUI-extension/app/docs/.DS_Store ADDED
Binary file (6.15 kB). View file
 
extensions/openOutpaint-webUI-extension/app/favicon.ico ADDED
extensions/openOutpaint-webUI-extension/app/index.html ADDED
@@ -0,0 +1,591 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>openOutpaint 🐠</title>
6
+ <!-- CSS Variables -->
7
+ <link href="css/colors.css?v=f732f19" rel="stylesheet" />
8
+ <link href="css/icons.css?v=e6f94af" rel="stylesheet" />
9
+
10
+ <link href="css/index.css?v=a1f5bff" rel="stylesheet" />
11
+ <link href="css/layers.css?v=92c0352" rel="stylesheet" />
12
+
13
+ <link href="css/ui/generic.css?v=30837f8" rel="stylesheet" />
14
+
15
+ <link href="css/ui/notifications.css?v=7b152de" rel="stylesheet" />
16
+ <link href="css/ui/workspace.css?v=2a9fdf7" rel="stylesheet" />
17
+ <link href="css/ui/history.css?v=0b03861" rel="stylesheet" />
18
+ <link href="css/ui/layers.css?v=1d66c2b" rel="stylesheet" />
19
+ <link href="css/ui/toolbar.css?v=109c78f" rel="stylesheet" />
20
+
21
+ <!-- Tool Specific CSS -->
22
+ <link href="css/ui/tool/dream.css?v=2d8a8ac" rel="stylesheet" />
23
+ <link href="css/ui/tool/stamp.css?v=6f5ce15" rel="stylesheet" />
24
+ <link href="css/ui/tool/colorbrush.css?v=57c8be5" rel="stylesheet" />
25
+
26
+ <link rel="icon" type="image/x-icon" href="favicon.ico" />
27
+ </head>
28
+
29
+ <body>
30
+ <!-- Main Toolbar -->
31
+ <div
32
+ id="infoContainer"
33
+ class="floating-window"
34
+ style="left: 10px; top: 10px">
35
+ <div id="infoTitleBar" class="draggable floating-window-title">
36
+ openOutpaint 🐠
37
+ <div style="flex: 1"></div>
38
+ <button id="settings-btn" class="ui icon header-button">
39
+ <div class="icon-settings"></div>
40
+ </button>
41
+ </div>
42
+ <div id="info" class="menu-container" style="min-width: 200px">
43
+ <div
44
+ id="workspace-select-area"
45
+ style="display: flex; margin-bottom: 5px">
46
+ <div id="workspace-select"></div>
47
+ <div class="buttons" style="display: flex">
48
+ <button
49
+ id="save-workspace-btn"
50
+ class="ui inline-icon icon-save workspace-btn"
51
+ title="Save Workspace"></button>
52
+ <button
53
+ id="rename-workspace-btn"
54
+ class="ui inline-icon icon-pencil workspace-btn"
55
+ title="Rename Workspace"></button>
56
+ <button
57
+ id="more-workspace-btn"
58
+ class="ui inline-icon icon-more-horizontal workspace-btn"
59
+ title="More Options"></button>
60
+ <div
61
+ id="more-workspace-menu"
62
+ class="workspace-collapsible collapsed">
63
+ <div>
64
+ <button
65
+ id="export-workspace-btn"
66
+ class="ui inline-icon icon-download workspace-btn"
67
+ title="Export Workspace"></button>
68
+ <button
69
+ id="import-workspace-btn"
70
+ class="ui inline-icon icon-upload workspace-btn"
71
+ title="Import Workspace"></button>
72
+ <button
73
+ id="delete-workspace-btn"
74
+ class="ui inline-icon icon-trash workspace-btn"
75
+ title="Delete Workspace"></button>
76
+ </div>
77
+ <div style="width: 5px; background-color: var(--c-primary)"></div>
78
+ </div>
79
+ <div style="width: 5px; background-color: var(--c-primary)"></div>
80
+ </div>
81
+ </div>
82
+
83
+ <div class="host-field-wrapper">
84
+ <div class="host-field">
85
+ <div class="label">Host</div>
86
+ <input id="host" value="http://127.0.0.1:7860" />
87
+ </div>
88
+ <div
89
+ id="connection-status-indicator"
90
+ class="connection-status before">
91
+ <span id="connection-status-indicator-text">Waiting</span>
92
+ </div>
93
+ </div>
94
+
95
+ <!-- Prompts section -->
96
+ <button type="button" class="collapsible">Prompts</button>
97
+ <div class="content prompt">
98
+ <div class="inputs">
99
+ <div class="prompt-wrapper">
100
+ <div class="prompt-indicator positive" title="Prompt"></div>
101
+ <textarea id="prompt" class="expandable"></textarea>
102
+ </div>
103
+ <div class="prompt-wrapper">
104
+ <div
105
+ class="prompt-indicator negative"
106
+ title="Negative Prompt"></div>
107
+ <textarea id="negPrompt" class="expandable"></textarea>
108
+ </div>
109
+ <div class="prompt-wrapper">
110
+ <div class="prompt-indicator styles" title="Styles"></div>
111
+ <div id="style-ac-mselect" style="flex-shrink: 1"></div>
112
+ </div>
113
+ </div>
114
+ <div class="prompt-history-wrapper">
115
+ <div class="prompt-history-container">
116
+ <div id="prompt-history"></div>
117
+ <button
118
+ id="prompt-history-btn"
119
+ class="prompt-history-btn"></button>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ <!-- SD section -->
124
+ <button type="button" class="collapsible">
125
+ Stable Diffusion settings
126
+ </button>
127
+ <div class="content">
128
+ <label>Model:</label>
129
+ <div id="models-ac-select"></div>
130
+ <button id="refreshModelsBtn" onclick="getModels(true)">
131
+ <img
132
+ class="refreshbutton"
133
+ src="./res/icons/refresh-cw.svg?v=f627140"
134
+ alt="refresh models"
135
+ title="refresh models" />
136
+ </button>
137
+ <label>Sampler:</label>
138
+ <div id="sampler-ac-select"></div>
139
+ <label for="seed">Seed (-1 for random):</label>
140
+ <br />
141
+ <input
142
+ type="number"
143
+ id="seed"
144
+ onchange="changeSeed()"
145
+ min="-1"
146
+ max="99999999999999999999"
147
+ value="-1"
148
+ step="1" />
149
+ <br />
150
+ <label>Lora:</label>
151
+ <div id="lora-ac-select"></div>
152
+ <input type="checkbox" id="cbxHRFix" onchange="changeHiResFix()" />
153
+ <label for="cbxHRFix">Apply Txt2Img HRfix</label>
154
+ <br />
155
+ <input
156
+ type="checkbox"
157
+ id="cbxHRFSquare"
158
+ onchange="changeHiResSquare()"
159
+ class="hrfix" />
160
+ <label for="cbxHRFSquare" class="hrfix">
161
+ Square Firstpass Aspect
162
+ </label>
163
+ <br class="hrfix" />
164
+ <div id="hrFixScale" class="hrfix"></div>
165
+ <div id="hrFixLockPx" class="hrfix"></div>
166
+ <div id="hrFixSteps" class="hrfix"></div>
167
+ <label id="hrFixLabel" class="hrfix">Choose HRfix upscaler</label>
168
+ <div id="hrFixUpscaler" class="hrfix"></div>
169
+ <div id="hrDenoising" class="hrfix"></div>
170
+ <input
171
+ type="checkbox"
172
+ id="cbxRestoreFaces"
173
+ onchange="changeRestoreFaces()" />
174
+ <label for="cbxRestoreFaces">Restore Faces</label>
175
+ <br />
176
+ <input
177
+ type="checkbox"
178
+ id="cbxSyncCursorSize"
179
+ onchange="changeSyncCursorSize()" />
180
+ <label for="cbxSyncCursorSize">Sync cursor size</label>
181
+ <br />
182
+ <div id="resolution"></div>
183
+ <div id="steps"></div>
184
+ <div id="cfgScale"></div>
185
+ <div id="batchSize"></div>
186
+ <div id="batchCount"></div>
187
+ <label for="maskBlur">Mask blur:</label>
188
+ <span id="maskBlurText"></span>
189
+ <br />
190
+ <input
191
+ type="number"
192
+ id="maskBlur"
193
+ name="maskBlur"
194
+ min="0"
195
+ max="256"
196
+ value="0"
197
+ step="1"
198
+ onchange="changeMaskBlur()" />
199
+ </div>
200
+ <!-- Extensions section -->
201
+ <button type="button" class="collapsible">Extensions</button>
202
+ <div class="content">
203
+ <input
204
+ type="checkbox"
205
+ id="cbxDynPrompts"
206
+ onchange="changeDynamicPromptsExtension()"
207
+ disabled="disabled" />
208
+ <label for="cbxDynPrompts">Dynamic Prompts</label>
209
+ <br />
210
+ <input
211
+ type="checkbox"
212
+ id="cbxControlNet"
213
+ onchange="changeControlNetExtension()"
214
+ disabled="disabled" />
215
+ <label for="cbxControlNet">ControlNet In/Outpainting</label>
216
+ <br class="controlNetElement" />
217
+ <label id="cnModuleLabel" class="controlNetElement">
218
+ Inpaint Preprocessor
219
+ </label>
220
+ <div id="controlNetModule-ac-select" class="controlNetElement"></div>
221
+ <label id="cnModelLabel" class="controlNetElement">Model</label>
222
+ <div id="controlNetModel-ac-select" class="controlNetElement"></div>
223
+ <label id="cnControlLabel" class="controlNetElement">
224
+ Inpaint Mode
225
+ </label>
226
+ <select id="controlNetMode-select" class="controlNetElement">
227
+ <option value="Balanced">balanced</option>
228
+ <option value="My prompt is more important">+prompt</option>
229
+ <option value="ControlNet is more important">+CN</option>
230
+ </select>
231
+ <br class="controlNetElement" />
232
+ <label id="cnResizeLabel" class="controlNetElement">
233
+ Resize Mode
234
+ </label>
235
+ <select id="controlNetResize-select" class="controlNetElement">
236
+ <option value="Just Resize">resize</option>
237
+ <option value="Crop and Resize">+crop</option>
238
+ <option value="Resize and Fill">+fill</option>
239
+ </select>
240
+ <br class="controlNetElement" />
241
+ <input
242
+ type="checkbox"
243
+ id="cbxControlNetReferenceLayer"
244
+ onchange="changeControlNetReference()"
245
+ class="controlNetElement" />
246
+ <label for="cbxControlNetReferenceLayer" class="controlNetElement">
247
+ Reference as 1st CN Unit
248
+ </label>
249
+ <br class="controlNetReferenceElement" />
250
+ <label id="cnReferenceModuleLabel" class="controlNetReferenceElement">
251
+ Reference Preprocessor
252
+ </label>
253
+ <div
254
+ id="controlNetReferenceModule-ac-select"
255
+ class="controlNetReferenceElement"></div>
256
+ <div
257
+ id="controlNetReferenceFidelity"
258
+ class="controlNetReferenceElement"></div>
259
+ <label id="cnResizeLabel" class="controlNetReferenceElement">
260
+ Reference Mode
261
+ </label>
262
+ <select
263
+ id="controlNetReferenceMode-select"
264
+ class="controlNetReferenceElement">
265
+ <option value="Balanced">balanced</option>
266
+ <option value="My prompt is more important">+prompt</option>
267
+ <option value="ControlNet is more important">+CN</option>
268
+ </select>
269
+ </div>
270
+ <!-- Save/load image section -->
271
+ <button type="button" class="collapsible">Save/Upscaling</button>
272
+ <div class="content">
273
+ <button onclick="downloadCanvas()">Save canvas</button>
274
+ <br />
275
+ <label>Choose upscaler</label>
276
+ <div id="upscaler-ac-select"></div>
277
+ <div id="upscaleX"></div>
278
+ <button onclick="upscaleAndDownload()">
279
+ Upscale (might take a sec)
280
+ </button>
281
+ <br />
282
+
283
+ <button onclick="newImage()">Clear canvas</button>
284
+ </div>
285
+ <!-- Debug info -->
286
+ <button type="button" class="collapsible">Debug info</button>
287
+ <div id="coords" class="content">
288
+ <label for="mouseX">mouseX:</label>
289
+ <span id="mouseX"></span>
290
+ <br />
291
+ <label for="mouseY">mouseY:</label>
292
+ <span id="mouseY"></span>
293
+ <br />
294
+ <label for="canvasX">canvasX:</label>
295
+ <span id="canvasX"></span>
296
+ <br />
297
+ <label for="canvasY">canvasY:</label>
298
+ <span id="canvasY"></span>
299
+ <br />
300
+ <label for="snapX">snapX:</label>
301
+ <span id="snapX"></span>
302
+ <br />
303
+ <label for="snapY">snapY:</label>
304
+ <span id="snapY"></span>
305
+ <br />
306
+ <label for="heldButton">Mouse button:</label>
307
+ <span id="heldButton"></span>
308
+ <br />
309
+ <button id="resetToDefaults" onclick="resetToDefaults()">
310
+ Reset to defaults
311
+ </button>
312
+ <button id="toggleDebugBtn" onclick="global.toggledebug()">
313
+ Toggle Debug
314
+ </button>
315
+ <br />
316
+ <span id="version">
317
+ <a href="https://github.com/zero01101/openOutpaint" target="_blank">
318
+ <s>Alpha release v0.0.16.5</s>
319
+ v20230812.001
320
+ </a>
321
+ <br />
322
+ <a
323
+ href="https://github.com/zero01101/openOutpaint/wiki/Manual"
324
+ target="_blank">
325
+ User Manual
326
+ </a>
327
+ </span>
328
+ <br />
329
+ <!-- <hr /> -->
330
+ </div>
331
+ <div style="display: flex; align-items: center">
332
+ <div
333
+ style="
334
+ flex: 1;
335
+ border-top: 1px black solid;
336
+ margin-right: 10px;
337
+ "></div>
338
+ Context Menu
339
+ <div
340
+ style="
341
+ flex: 1;
342
+ border-top: 1px black solid;
343
+ margin-left: 10px;
344
+ "></div>
345
+ </div>
346
+ <div id="tool-context" class="context-menu"></div>
347
+ </div>
348
+ </div>
349
+
350
+ <!-- History -->
351
+ <div id="ui-history" class="floating-window" style="right: 10px; top: 10px">
352
+ <div class="draggable floating-window-title">
353
+ History
354
+ <div style="flex: 1"></div>
355
+ <button
356
+ id="history-logs-btn"
357
+ class="ui icon header-button"
358
+ title="Generate History Log">
359
+ <div class="icon-scroll"></div>
360
+ </button>
361
+ </div>
362
+ <div class="menu-container" style="min-width: 200px">
363
+ <div id="history" class="history"></div>
364
+ <div class="button-array" style="padding: 10px">
365
+ <button type="button" onclick="commands.undo()" class="button tool">
366
+ undo
367
+ </button>
368
+ <button type="button" onclick="commands.redo()" class="button tool">
369
+ redo
370
+ </button>
371
+ </div>
372
+ </div>
373
+ </div>
374
+
375
+ <!-- Layers -->
376
+ <div
377
+ id="ui-layers"
378
+ class="floating-window"
379
+ style="right: 10px; bottom: 10px">
380
+ <div class="draggable floating-window-title">
381
+ Layers
382
+ <div style="flex: 1"></div>
383
+ <button
384
+ id="unzoom-btn"
385
+ class="ui icon header-button"
386
+ title="Reset Zoom to 1x"
387
+ onclick="unzoom()">
388
+ <div class="icon-unzoom"></div>
389
+ </button>
390
+ </div>
391
+ <div class="menu-container" style="min-width: 200px">
392
+ <div class="layer-manager">
393
+ <div id="layer-list" class="layer-list"></div>
394
+ <div class="ui separator"></div>
395
+ <div class="layer-list-actions">
396
+ <button
397
+ type="button"
398
+ title="Add Layer"
399
+ onclick="commands.runCommand('addLayer', 'Added Layer', {})"
400
+ class="ui icon button">
401
+ <div class="icon-file-plus"></div>
402
+ </button>
403
+
404
+ <button
405
+ type="button"
406
+ title="Move Layer Up"
407
+ onclick="commands.runCommand('moveLayer', 'Moved Layer Up',{delta: 1})"
408
+ class="ui icon button">
409
+ <div class="icon-chevron-up"></div>
410
+ </button>
411
+
412
+ <button
413
+ type="button"
414
+ title="Move Layer Down"
415
+ onclick="commands.runCommand('moveLayer', 'Moved Layer Down', {delta: -1})"
416
+ class="ui icon button">
417
+ <div class="icon-chevron-down"></div>
418
+ </button>
419
+
420
+ <button
421
+ type="button"
422
+ title="Merge Layer Down"
423
+ onclick="commands.runCommand('mergeLayer', 'Merged Layer Down')"
424
+ class="ui icon button">
425
+ <div class="icon-chevron-flat-down"></div>
426
+ </button>
427
+
428
+ <button
429
+ type="button"
430
+ title="Delete Layer"
431
+ onclick="commands.runCommand('deleteLayer', 'Deleted Layer')"
432
+ class="ui icon button">
433
+ <div class="icon-file-x"></div>
434
+ </button>
435
+ </div>
436
+ </div>
437
+ </div>
438
+ </div>
439
+
440
+ <!-- Scripts-->
441
+ <div
442
+ id="ui-script"
443
+ class="floating-window"
444
+ style="right: 10px; top: 330px; display: none">
445
+ <div class="draggable floating-window-title">Script</div>
446
+ <div class="menu-container" style="min-width: 200px">
447
+ <div id="script-select" class="script-select">
448
+ <select id="script-selector" onchange="changeScript(event)">
449
+ <!-- <option id="no_selected_script" value="">Select a script...</option>
450
+ <option id="custom" value="custom">Custom</option> -->
451
+ </select>
452
+ <!-- <button
453
+ id="save-custom-script"
454
+ disabled="disabled"
455
+ title="Save custom script"
456
+ onclick="saveCustomScript()">
457
+ <image src="./res/icons/save.svg" width="60%"></image>
458
+ </button> -->
459
+ </div>
460
+ <div id="script-name" class="script-name">
461
+ <label for="script-name-input">Script Name:</label>
462
+ <br />
463
+ <input
464
+ id="script-name-input"
465
+ disabled="disabled"
466
+ onfocusout="storeUserscriptVal(event, 'name')" />
467
+ <br />
468
+ </div>
469
+ <div id="script-args" class="script-args">
470
+ <label for="script-args-input">Script Args List:</label>
471
+ <br />
472
+ <textarea
473
+ id="script-args-input"
474
+ onfocusout="storeUserscriptVal(event, 'args')"></textarea>
475
+ <br />
476
+ </div>
477
+ </div>
478
+ </div>
479
+
480
+ <!-- Toolbar -->
481
+ <div
482
+ id="ui-toolbar"
483
+ class="floating-window toolbar"
484
+ style="right: 270px; top: 10px">
485
+ <div class="draggable handle">
486
+ <span class="line"></span>
487
+ </div>
488
+ <div class="lock-indicator" id="toolbar-lock-indicator"></div>
489
+ <div class="toolbar-section"></div>
490
+ </div>
491
+
492
+ <!-- Canvases -->
493
+ <div id="layer-render" class="layer-render-target"></div>
494
+
495
+ <!-- Overlay -->
496
+ <canvas id="layer-overlay" class="overlay-canvas"></canvas>
497
+ <canvas id="layer-debug-overlay" class="overlay-canvas"></canvas>
498
+
499
+ <!-- Page Overlay -->
500
+ <div id="page-overlay-wrapper" class="page-overlay invisible">
501
+ <div class="page-overlay-window">
502
+ <div class="title">
503
+ Settings
504
+ <button id="settings-btn-close" class="close"></button>
505
+ </div>
506
+ <div class="ui separator"></div>
507
+ <iframe
508
+ id="page-overlay"
509
+ src="pages/configuration.html?v=fdbd833"></iframe>
510
+ </div>
511
+ </div>
512
+
513
+ <!-- Basics -->
514
+ <script src="js/global.js?v=ac30d16" type="text/javascript"></script>
515
+ <script src="js/defaults.js?v=5b06818" type="text/javascript"></script>
516
+ <script src="js/extensions.js?v=0bd1fbe" type="text/javascript"></script>
517
+
518
+ <!-- Base Libs -->
519
+ <script src="js/lib/util.js?v=379aef7" type="text/javascript"></script>
520
+ <script
521
+ src="js/lib/notifications.js?v=270db88"
522
+ type="text/javascript"></script>
523
+ <script src="js/lib/events.js?v=2ab7933" type="text/javascript"></script>
524
+ <script src="js/lib/db.js?v=434363b" type="text/javascript"></script>
525
+ <script src="js/lib/input.js?v=769485c" type="text/javascript"></script>
526
+ <script src="js/lib/layers.js?v=26b7436" type="text/javascript"></script>
527
+ <script src="js/lib/commands.js?v=ad60afc" type="text/javascript"></script>
528
+
529
+ <script src="js/lib/toolbar.js?v=4fcf718" type="text/javascript"></script>
530
+ <script src="js/lib/ui.js?v=17014b3" type="text/javascript"></script>
531
+
532
+ <script
533
+ src="js/initalize/layers.populate.js?v=066dc8e"
534
+ type="text/javascript"></script>
535
+
536
+ <!-- Configuration -->
537
+ <script src="js/config.js?v=9747005" type="text/javascript"></script>
538
+ <script src="js/theme.js?v=435cc1b" type="text/javascript"></script>
539
+
540
+ <!-- Content -->
541
+ <script src="js/prompt.js?v=7a1c68c" type="text/javascript"></script>
542
+ <script src="js/index.js?v=d4006e8" type="text/javascript"></script>
543
+
544
+ <script
545
+ src="js/ui/floating/history.js?v=4f29db4"
546
+ type="text/javascript"></script>
547
+ <script
548
+ src="js/ui/floating/layers.js?v=3f5807f"
549
+ type="text/javascript"></script>
550
+
551
+ <!-- Load Tools -->
552
+ <script
553
+ src="js/ui/tool/generic.js?v=3e678e0"
554
+ type="text/javascript"></script>
555
+
556
+ <script src="js/ui/tool/dream.js?v=95bd3f0" type="text/javascript"></script>
557
+ <script
558
+ src="js/ui/tool/maskbrush.js?v=e9bd0eb"
559
+ type="text/javascript"></script>
560
+ <script
561
+ src="js/ui/tool/colorbrush.js?v=84ff9fa"
562
+ type="text/javascript"></script>
563
+ <script
564
+ src="js/ui/tool/select.js?v=dfacef5"
565
+ type="text/javascript"></script>
566
+ <script src="js/ui/tool/stamp.js?v=4494df6" type="text/javascript"></script>
567
+ <script
568
+ src="js/ui/tool/interrogate.js?v=dd45b4a"
569
+ type="text/javascript"></script>
570
+
571
+ <!-- Initialize -->
572
+ <script
573
+ src="js/initalize/workspace.populate.js?v=925431d"
574
+ type="text/javascript"></script>
575
+ <script
576
+ src="js/initalize/shortcuts.populate.js?v=e68546f"
577
+ type="text/javascript"></script>
578
+ <script
579
+ src="js/initalize/toolbar.populate.js?v=c1ca438"
580
+ type="text/javascript"></script>
581
+ <script
582
+ src="js/initalize/debug.populate.js?v=64ad17f"
583
+ type="text/javascript"></script>
584
+ <script
585
+ src="js/initalize/ui.populate.js?v=b59b288"
586
+ type="text/javascript"></script>
587
+
588
+ <!-- Deals with webui communication -->
589
+ <script src="js/webui.js?v=ccd423a" type="text/javascript"></script>
590
+ </body>
591
+ </html>
extensions/openOutpaint-webUI-extension/app/js/config.js ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This is a file for static unchanging global configurations.
3
+ *
4
+ * Do NOT confuse with settings, which are modifiable by either the settings menu, or in the application itself.
5
+ */
6
+ const config = makeReadOnly(
7
+ {
8
+ // Grid Size
9
+ gridSize: 64,
10
+
11
+ // Scroll Tick Limit (How much must scroll to reach next tick)
12
+ wheelTickSize: 50,
13
+
14
+ /** Select Tool */
15
+ // Handle Draw Size
16
+ handleDrawSize: 12,
17
+ // Handle Draw Hover Scale
18
+ handleDrawHoverScale: 1.3,
19
+ // Handle Detect Size
20
+ handleDetectSize: 20,
21
+ // Rotate Handle Distance (from selection)
22
+ rotateHandleDistance: 32,
23
+
24
+ // Rotation Snapping Distance
25
+ rotationSnappingDistance: (10 * Math.PI) / 180,
26
+ // Rotation Snapping Angles
27
+ rotationSnappingAngles: [
28
+ (-Math.PI * 4) / 4,
29
+ (-Math.PI * 3) / 4,
30
+ (-Math.PI * 2) / 4,
31
+ (-Math.PI * 1) / 4,
32
+ 0,
33
+ (Math.PI * 1) / 4,
34
+ (Math.PI * 2) / 4,
35
+ (Math.PI * 3) / 4,
36
+ (Math.PI * 4) / 4,
37
+ ],
38
+
39
+ // Endpoint
40
+ api: makeReadOnly({path: "/sdapi/v1/"}),
41
+
42
+ // Default notification timeout
43
+ notificationTimeout: 8000,
44
+ notificationHighlightAnimationDuration: 200,
45
+
46
+ /**
47
+ * Interrogate Tool
48
+ */
49
+ interrogateToolNotificationTimeout: 120000, // Default is two minutes
50
+ },
51
+ "config"
52
+ );
extensions/openOutpaint-webUI-extension/app/js/defaults.js ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Default settings for local configurations
3
+ */
4
+ const localDefaults = {
5
+ /** Default Host */
6
+ host: "http://127.0.0.1:7860",
7
+ };
8
+
9
+ /**
10
+ * Default settings for workspace configurations
11
+ */
12
+ const workspaceDefaults = {
13
+ /** Default Prompt - REQ */
14
+ prompt: "ocean floor scientific expedition, underwater wildlife",
15
+ /** Default Negative Prompt - REQ */
16
+ neg_prompt:
17
+ "people, person, humans, human, divers, diver, glitch, error, text, watermark, bad quality, blurry",
18
+ /** Default Stable Diffusion Seed - REQ */
19
+ seed: -1,
20
+
21
+ /** Default CFG Scale - REQ */
22
+ cfg_scale: 7.0,
23
+ /** Default steps - REQ */
24
+ steps: 30,
25
+
26
+ /** Default Resolution */
27
+ resolution: 512,
28
+ };
extensions/openOutpaint-webUI-extension/app/js/extensions.js ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Extensions helper thing or class or whatever
3
+ */
4
+
5
+ const extensions = {
6
+ // alwaysOnScriptsData: {},
7
+ alwaysOnScripts: false,
8
+ controlNetEnabled: false,
9
+ controlNetActive: false,
10
+ controlNetReferenceActive: false,
11
+ controlNetReferenceFidelity: 0.5,
12
+ selectedControlNetModel: null,
13
+ selectedControlNetModule: null,
14
+ selectedCNReferenceModule: null,
15
+ controlNetModelCount: 0,
16
+ dynamicPromptsEnabled: false,
17
+ dynamicPromptsActive: false,
18
+ dynamicPromptsAlwaysonScriptName: null, //GRUMBLE GRUMBLE
19
+ enabledExtensions: [],
20
+ controlNetModels: null,
21
+ controlNetModules: null,
22
+
23
+ async getExtensions(
24
+ controlNetModelAutoComplete,
25
+ controlNetModuleAutoComplete,
26
+ controlNetReferenceModuleAutoComplete
27
+ ) {
28
+ const allowedExtensions = [
29
+ "controlnet",
30
+ // "none",
31
+ // "adetailer", // no API, can't verify available models
32
+ "dynamic prompts", //seriously >:( why put version in the name, now i have to fuzzy match it - just simply enabled or not? no API but so so good
33
+ //"segment anything", // ... API lets me get model but not processor?!?!?!
34
+ //"self attention guidance", // no API but useful, just enabled button, scale and threshold sliders?
35
+ ];
36
+ // check http://127.0.0.1:7860/sdapi/v1/scripts for extensions
37
+ // if any of the allowed extensions are found, add them to the list
38
+ var url = document.getElementById("host").value + "/sdapi/v1/scripts";
39
+ try {
40
+ const response = await fetch(url);
41
+ const data = await response.json();
42
+ // enable checkboxes for extensions based on existence in data
43
+ data.img2img
44
+ .filter((extension) => {
45
+ return allowedExtensions.some((allowedExtension) => {
46
+ return extension.toLowerCase().includes(allowedExtension);
47
+ });
48
+ })
49
+ .forEach((extension) => {
50
+ this.enabledExtensions.push(extension);
51
+ });
52
+ } catch (e) {
53
+ console.warn("[index] Failed to fetch extensions");
54
+ console.warn(e);
55
+ }
56
+ this.checkForDynamicPrompts();
57
+ this.checkForControlNet(
58
+ controlNetModelAutoComplete,
59
+ controlNetModuleAutoComplete,
60
+ controlNetReferenceModuleAutoComplete
61
+ );
62
+ //checkForSAM(); //or inpaintAnything or something i dunno
63
+ //checkForADetailer(); //? this one seems iffy
64
+ //checkForSAG(); //??
65
+ },
66
+
67
+ async checkForDynamicPrompts() {
68
+ if (
69
+ this.enabledExtensions.filter((e) => e.includes("dynamic prompts"))
70
+ .length > 0
71
+ ) {
72
+ // Dynamic Prompts found, enable checkbox
73
+ this.alwaysOnScripts = true;
74
+ this.dynamicPromptsAlwaysonScriptName =
75
+ this.enabledExtensions[
76
+ this.enabledExtensions.findIndex((e) => e.includes("dynamic prompts"))
77
+ ];
78
+ // this.alwaysOnScriptsData[this.dynamicPromptsAlwaysonScriptName] = {};
79
+ this.dynamicPromptsEnabled = true;
80
+ document.getElementById("cbxDynPrompts").disabled = false;
81
+ }
82
+ // basically param 0 is true for on, false for off, that's it
83
+ },
84
+
85
+ async checkForControlNet(
86
+ controlNetModelAutoComplete,
87
+ controlNetModuleAutoComplete,
88
+ controlNetReferenceModuleAutoComplete
89
+ ) {
90
+ var url = document.getElementById("host").value + "/controlnet/version";
91
+
92
+ if (
93
+ this.enabledExtensions.filter((e) => e.includes("controlnet")).length > 0
94
+ ) {
95
+ try {
96
+ const response = await fetch(url);
97
+ const data = await response.json();
98
+
99
+ if (data.version > 0) {
100
+ // ControlNet found
101
+ this.alwaysOnScripts = true;
102
+ this.controlNetEnabled = true;
103
+ document.getElementById("cbxControlNet").disabled = false;
104
+ // ok cool so now we can get the models and modules
105
+ this.getModels(controlNetModelAutoComplete);
106
+ this.getModules(
107
+ controlNetModuleAutoComplete,
108
+ controlNetReferenceModuleAutoComplete
109
+ );
110
+ }
111
+ url = document.getElementById("host").value + "/controlnet/settings";
112
+ try {
113
+ const response2 = await fetch(url);
114
+ const data2 = await response2.json();
115
+ if (data2.control_net_max_models_num < 2) {
116
+ document.getElementById("cbxControlNetReferenceLayer").disabled =
117
+ "disabled";
118
+ console.warn(
119
+ "[extensions] ControlNet reference layer disabled due to insufficient units enabled in settings - cannot be enabled via API, please increase to at least 2 units manually"
120
+ );
121
+ }
122
+ } catch (ex) {}
123
+ } catch (e) {
124
+ // ??
125
+ global.controlnetAPI = false;
126
+ }
127
+ } else {
128
+ global.controlnetAPI = false;
129
+ }
130
+ },
131
+ async getModels(controlNetModelAutoComplete) {
132
+ // only worry about inpaint models for now
133
+ var url = document.getElementById("host").value + "/controlnet/model_list";
134
+
135
+ try {
136
+ const response = await fetch(url);
137
+ const data = await response.json();
138
+
139
+ this.controlNetModels = data.model_list;
140
+ } catch (e) {
141
+ console.warn("[extensions] Failed to fetch controlnet models");
142
+ console.warn(e);
143
+ }
144
+
145
+ let opt = null;
146
+ opt = this.controlNetModels
147
+ .filter((m) => m.includes("inpaint"))
148
+ .map((option) => ({
149
+ name: option,
150
+ value: option,
151
+ }));
152
+
153
+ controlNetModelAutoComplete.options = opt;
154
+ },
155
+ async getModules(
156
+ controlNetModuleAutoComplete,
157
+ controlNetReferenceModuleAutoComplete
158
+ ) {
159
+ const allowedModules = ["reference", "inpaint"];
160
+ var url = document.getElementById("host").value + "/controlnet/module_list";
161
+
162
+ try {
163
+ const response = await fetch(url);
164
+ const data = await response.json();
165
+
166
+ this.controlNetModules = data;
167
+ } catch (e) {
168
+ console.warn("[extensions] Failed to fetch controlnet modules");
169
+ console.warn(e);
170
+ }
171
+
172
+ let opt = null;
173
+ opt = this.controlNetModules.module_list
174
+ .filter((m) => m.includes("inpaint")) // why is there just "inpaint" in the modules if it's not in the ui
175
+ .map((option) => ({
176
+ name: option,
177
+ value: option,
178
+ }));
179
+
180
+ opt.push({
181
+ name: "inpaint_global_harmonious",
182
+ value: "inpaint_global_harmonious", // WTF WHY IS THIS ONE NOT LISTED IN MODULES BUT DISTINCT IN THE API CALL?!?!?!??!??! it is slightly different from "inpaint" from what i can tell
183
+ });
184
+
185
+ controlNetModuleAutoComplete.options = opt;
186
+
187
+ opt = this.controlNetModules.module_list
188
+ .filter((m) => m.includes("reference"))
189
+ .map((option) => ({
190
+ name: option,
191
+ value: option,
192
+ }));
193
+
194
+ controlNetReferenceModuleAutoComplete.options = opt;
195
+ },
196
+ };
extensions/openOutpaint-webUI-extension/app/js/global.js ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Stores global variables without polluting the global namespace.
3
+ */
4
+
5
+ const global = {
6
+ // If this is the first run of openOutpaint
7
+ get firstRun() {
8
+ return this._firstRun;
9
+ },
10
+
11
+ // Connection
12
+ _connection: "offline",
13
+ set connection(v) {
14
+ this._connection = v;
15
+
16
+ toolbar &&
17
+ toolbar.currentTool &&
18
+ toolbar.currentTool.state.redraw &&
19
+ toolbar.currentTool.state.redraw();
20
+ },
21
+ get connection() {
22
+ return this._connection;
23
+ },
24
+
25
+ // If there is a selected input
26
+ hasActiveInput: false,
27
+
28
+ // If cursor size sync is enabled
29
+ syncCursorSize: false,
30
+
31
+ // If debugging is enabled
32
+ _debug: false,
33
+ set debug(v) {
34
+ if (debugLayer) {
35
+ if (v) {
36
+ debugLayer.unhide();
37
+ } else {
38
+ debugLayer.hide();
39
+ }
40
+ }
41
+
42
+ this._debug = v;
43
+ },
44
+ get debug() {
45
+ return this._debug;
46
+ },
47
+ /**
48
+ * Toggles debugging.
49
+ */
50
+ toggledebug() {
51
+ this.debug = !this.debug;
52
+ },
53
+
54
+ // HRFix compatibility shenanigans
55
+ isOldHRFix: false,
56
+
57
+ // WebUI object to communitate with parent window
58
+ webui: null,
59
+ };
60
+
61
+ global._firstRun = !localStorage.getItem("openoutpaint/host");
extensions/openOutpaint-webUI-extension/app/js/index.js ADDED
@@ -0,0 +1,1685 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //TODO FIND OUT WHY I HAVE TO RESIZE A TEXTBOX AND THEN START USING IT TO AVOID THE 1px WHITE LINE ON LEFT EDGES DURING IMG2IMG
2
+ //...lmao did setting min width 200 on info div fix that accidentally? once the canvas is infinite and the menu bar is hideable it'll probably be a problem again
3
+
4
+ /**
5
+ * Workaround for Firefox bug #733698
6
+ *
7
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=733698
8
+ *
9
+ * Workaround by https://github.com/subzey on https://gist.github.com/subzey/2030480
10
+ *
11
+ * Replaces and handles NS_ERROR_FAILURE errors triggered by 733698.
12
+ */
13
+ (function () {
14
+ var FakeTextMetrics,
15
+ proto,
16
+ fontSetterNative,
17
+ measureTextNative,
18
+ fillTextNative,
19
+ strokeTextNative;
20
+
21
+ if (
22
+ !window.CanvasRenderingContext2D ||
23
+ !window.TextMetrics ||
24
+ !(proto = window.CanvasRenderingContext2D.prototype) ||
25
+ !proto.hasOwnProperty("font") ||
26
+ !proto.hasOwnProperty("mozTextStyle") ||
27
+ typeof proto.__lookupSetter__ !== "function" ||
28
+ !(fontSetterNative = proto.__lookupSetter__("font"))
29
+ ) {
30
+ return;
31
+ }
32
+
33
+ proto.__defineSetter__("font", function (value) {
34
+ try {
35
+ return fontSetterNative.call(this, value);
36
+ } catch (e) {
37
+ if (e.name !== "NS_ERROR_FAILURE") {
38
+ throw e;
39
+ }
40
+ }
41
+ });
42
+
43
+ measureTextNative = proto.measureText;
44
+ FakeTextMetrics = function () {
45
+ this.width = 0;
46
+ this.isFake = true;
47
+ this.__proto__ = window.TextMetrics.prototype;
48
+ };
49
+ proto.measureText = function ($0) {
50
+ try {
51
+ return measureTextNative.apply(this, arguments);
52
+ } catch (e) {
53
+ if (e.name !== "NS_ERROR_FAILURE") {
54
+ throw e;
55
+ } else {
56
+ return new FakeTextMetrics();
57
+ }
58
+ }
59
+ };
60
+
61
+ fillTextNative = proto.fillText;
62
+ proto.fillText = function ($0, $1, $2, $3) {
63
+ try {
64
+ fillTextNative.apply(this, arguments);
65
+ } catch (e) {
66
+ if (e.name !== "NS_ERROR_FAILURE") {
67
+ throw e;
68
+ }
69
+ }
70
+ };
71
+
72
+ strokeTextNative = proto.strokeText;
73
+ proto.strokeText = function ($0, $1, $2, $3) {
74
+ try {
75
+ strokeTextNative.apply(this, arguments);
76
+ } catch (e) {
77
+ if (e.name !== "NS_ERROR_FAILURE") {
78
+ throw e;
79
+ }
80
+ }
81
+ };
82
+ })();
83
+
84
+ // Parse url parameters
85
+ const urlParams = new URLSearchParams(window.location.search);
86
+
87
+ window.onload = startup;
88
+
89
+ var stableDiffusionData = {
90
+ //includes img2img data but works for txt2img just fine
91
+ prompt: "",
92
+ negative_prompt: "",
93
+ seed: -1,
94
+ cfg_scale: null,
95
+ sampler_index: "DDIM",
96
+ steps: null,
97
+ denoising_strength: 1,
98
+ mask_blur: 0,
99
+ batch_size: null,
100
+ width: 512,
101
+ height: 512,
102
+ n_iter: null, // batch count
103
+ mask: "",
104
+ init_images: [],
105
+ inpaint_full_res: false,
106
+ inpainting_fill: 1,
107
+ outpainting_fill: 2,
108
+ enable_hr: false,
109
+ restore_faces: false,
110
+ //firstphase_width: 0,
111
+ //firstphase_height: 0, //20230102 welp looks like the entire way HRfix is implemented has become bonkersly different
112
+ hr_scale: 2.0,
113
+ hr_upscaler: "None",
114
+ hr_second_pass_steps: 0,
115
+ hr_resize_x: 0,
116
+ hr_resize_y: 0,
117
+ hr_square_aspect: false,
118
+ styles: [],
119
+ // here's some more fields that might be useful
120
+
121
+ // ---txt2img specific:
122
+ // "enable_hr": false, // hires fix
123
+ // "denoising_strength": 0, // ok this is in both txt and img2img but txt2img only applies it if enable_hr == true
124
+ // "firstphase_width": 0, // hires fp w
125
+ // "firstphase_height": 0, // see above s/w/h/
126
+
127
+ // ---img2img specific
128
+ // "init_images": [ // imageS!??!? wtf maybe for batch img2img?? i just dump one base64 in here
129
+ // "string"
130
+ // ],
131
+ // "resize_mode": 0,
132
+ // "denoising_strength": 0.75, // yeah see
133
+ // "mask": "string", // string is just a base64 image
134
+ // "mask_blur": 4,
135
+ // "inpainting_fill": 0, // 0- fill, 1- orig, 2- latent noise, 3- latent nothing
136
+ // "inpaint_full_res": true,
137
+ // "inpaint_full_res_padding": 0, // px
138
+ // "inpainting_mask_invert": 0, // bool??????? wtf
139
+ // "include_init_images": false // ??????
140
+ };
141
+
142
+ // stuff things use
143
+ var host = "";
144
+ var url = "/sdapi/v1/";
145
+ const basePixelCount = 64; //64 px - ALWAYS 64 PX
146
+ var focused = true;
147
+ let defaultScripts = {};
148
+ let userScripts = {};
149
+
150
+ function startup() {
151
+ testHostConfiguration();
152
+ loadSettings();
153
+
154
+ const hostEl = document.getElementById("host");
155
+ testHostConnection().then((checkConnection) => {
156
+ hostEl.onchange = () => {
157
+ host = hostEl.value.endsWith("/")
158
+ ? hostEl.value.substring(0, hostEl.value.length - 1)
159
+ : hostEl.value;
160
+ hostEl.value = host;
161
+ localStorage.setItem("openoutpaint/host", host);
162
+ checkConnection();
163
+ };
164
+ });
165
+
166
+ drawBackground();
167
+ changeMaskBlur();
168
+ changeSmoothRendering();
169
+ changeSeed();
170
+ changeHiResFix();
171
+ changeHiResSquare();
172
+ changeRestoreFaces();
173
+ changeSyncCursorSize();
174
+ changeControlNetExtension();
175
+ changeControlNetReference();
176
+ checkFocus();
177
+ refreshScripts();
178
+ }
179
+
180
+ function setFixedHost(h, changePromptMessage) {
181
+ console.info(`[index] Fixed host to '${h}'`);
182
+ const hostInput = document.getElementById("host");
183
+ host = h;
184
+ hostInput.value = h;
185
+ hostInput.readOnly = true;
186
+ hostInput.style.cursor = "default";
187
+ hostInput.style.backgroundColor = "#ddd";
188
+ hostInput.addEventListener("dblclick", async () => {
189
+ if (await notifications.dialog("Host is Locked", changePromptMessage)) {
190
+ hostInput.style.backgroundColor = null;
191
+ hostInput.style.cursor = null;
192
+ hostInput.readOnly = false;
193
+ hostInput.focus();
194
+ }
195
+ });
196
+ }
197
+
198
+ /**
199
+ * Initial connection checks
200
+ */
201
+ function testHostConfiguration() {
202
+ /**
203
+ * Check host configuration
204
+ */
205
+ const hostEl = document.getElementById("host");
206
+ hostEl.value = localStorage.getItem("openoutpaint/host");
207
+
208
+ const requestHost = (prompt, def = "http://127.0.0.1:7860") => {
209
+ let value = null;
210
+
211
+ if (!urlParams.has("noprompt")) value = window.prompt(prompt, def);
212
+ if (value === null) value = def;
213
+
214
+ value = value.endsWith("/") ? value.substring(0, value.length - 1) : value;
215
+ host = value;
216
+ hostEl.value = host;
217
+ localStorage.setItem("openoutpaint/host", host);
218
+ };
219
+
220
+ const current = localStorage.getItem("openoutpaint/host");
221
+ if (current) {
222
+ if (!current.match(/^https?:\/\/[a-z0-9][a-z0-9.]+[a-z0-9](:[0-9]+)?$/i))
223
+ requestHost(
224
+ "Host seems to be invalid! Please fix your host here:",
225
+ current
226
+ );
227
+ else
228
+ host = current.endsWith("/")
229
+ ? current.substring(0, current.length - 1)
230
+ : current;
231
+ } else {
232
+ requestHost(
233
+ "This seems to be the first time you are using openOutpaint! Please set your host here:"
234
+ );
235
+ }
236
+ }
237
+
238
+ async function testHostConnection() {
239
+ class CheckInProgressError extends Error {}
240
+
241
+ const connectionIndicator = document.getElementById(
242
+ "connection-status-indicator"
243
+ );
244
+
245
+ let connectionStatus = false;
246
+ let firstTimeOnline = true;
247
+
248
+ const setConnectionStatus = (status) => {
249
+ const connectionIndicatorText = document.getElementById(
250
+ "connection-status-indicator-text"
251
+ );
252
+
253
+ const statuses = {
254
+ online: () => {
255
+ connectionIndicator.classList.add("online");
256
+ connectionIndicator.classList.remove(
257
+ "webui-issue",
258
+ "offline",
259
+ "before",
260
+ "server-error"
261
+ );
262
+ connectionIndicatorText.textContent = connectionIndicator.title =
263
+ "Connected";
264
+ connectionStatus = true;
265
+ },
266
+ error: () => {
267
+ connectionIndicator.classList.add("server-error");
268
+ connectionIndicator.classList.remove(
269
+ "online",
270
+ "offline",
271
+ "before",
272
+ "webui-issue"
273
+ );
274
+ connectionIndicatorText.textContent = "Error";
275
+ connectionIndicator.title =
276
+ "Server is online, but is returning an error response";
277
+ connectionStatus = false;
278
+ },
279
+ corsissue: () => {
280
+ connectionIndicator.classList.add("webui-issue");
281
+ connectionIndicator.classList.remove(
282
+ "online",
283
+ "offline",
284
+ "before",
285
+ "server-error"
286
+ );
287
+ connectionIndicatorText.textContent = "CORS";
288
+ connectionIndicator.title =
289
+ "Server is online, but CORS is blocking our requests";
290
+ connectionStatus = false;
291
+ },
292
+ apiissue: () => {
293
+ connectionIndicator.classList.add("webui-issue");
294
+ connectionIndicator.classList.remove(
295
+ "online",
296
+ "offline",
297
+ "before",
298
+ "server-error"
299
+ );
300
+ connectionIndicatorText.textContent = "API";
301
+ connectionIndicator.title =
302
+ "Server is online, but the API seems to be disabled";
303
+ connectionStatus = false;
304
+ },
305
+ offline: () => {
306
+ connectionIndicator.classList.add("offline");
307
+ connectionIndicator.classList.remove(
308
+ "webui-issue",
309
+ "online",
310
+ "before",
311
+ "server-error"
312
+ );
313
+ connectionIndicatorText.textContent = "Offline";
314
+ connectionIndicator.title =
315
+ "Server seems to be offline. Please check the console for more information.";
316
+ connectionStatus = false;
317
+ },
318
+ before: () => {
319
+ connectionIndicator.classList.add("before");
320
+ connectionIndicator.classList.remove(
321
+ "webui-issue",
322
+ "online",
323
+ "offline",
324
+ "server-error"
325
+ );
326
+ connectionIndicatorText.textContent = "Waiting";
327
+ connectionIndicator.title = "Waiting for check to complete.";
328
+ connectionStatus = false;
329
+ },
330
+ };
331
+
332
+ statuses[status] &&
333
+ (() => {
334
+ statuses[status]();
335
+ global.connection = status;
336
+ })();
337
+ };
338
+
339
+ setConnectionStatus("before");
340
+
341
+ let checkInProgress = false;
342
+
343
+ const checkConnection = async (
344
+ notify = false,
345
+ simpleProgressStatus = false
346
+ ) => {
347
+ const apiIssueResult = () => {
348
+ setConnectionStatus("apiissue");
349
+ const message = `The host is online, but the API seems to be disabled.<br>Have you run the webui with the flag '--api', or is the flag '--gradio-debug' currently active?`;
350
+ console.error(message);
351
+ if (notify)
352
+ notifications.notify(message, {
353
+ type: NotificationType.ERROR,
354
+ timeout: config.notificationTimeout * 2,
355
+ });
356
+ };
357
+
358
+ const offlineResult = () => {
359
+ setConnectionStatus("offline");
360
+ const message = `The connection with the host returned an error: ${response.status} - ${response.statusText}`;
361
+ console.error(message);
362
+ if (notify)
363
+ notifications.notify(message, {
364
+ type: NotificationType.ERROR,
365
+ timeout: config.notificationTimeout * 2,
366
+ });
367
+ };
368
+ if (checkInProgress)
369
+ throw new CheckInProgressError(
370
+ "Check is currently in progress, please try again"
371
+ );
372
+ checkInProgress = true;
373
+ var url = document.getElementById("host").value + "/startup-events";
374
+ // Attempt normal request
375
+ try {
376
+ if (simpleProgressStatus) {
377
+ const response = await fetch(
378
+ document.getElementById("host").value + "/sdapi/v1/progress" // seems to be the "lightest" endpoint?
379
+ );
380
+ switch (response.status) {
381
+ case 200: {
382
+ setConnectionStatus("online");
383
+ break;
384
+ }
385
+ case 404: {
386
+ apiIssueResult();
387
+ break;
388
+ }
389
+ default: {
390
+ offlineResult();
391
+ }
392
+ }
393
+ } else {
394
+ // Check if API is available
395
+ const response = await fetch(
396
+ document.getElementById("host").value + "/sdapi/v1/options"
397
+ );
398
+ const optionsdata = await response.json();
399
+ if (optionsdata["use_scale_latent_for_hires_fix"]) {
400
+ const message = `You are using an outdated version of A1111 webUI.<br>The HRfix options will not work until you update to at least commit ef27a18 or newer.<br>(https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/ef27a18b6b7cb1a8eebdc9b2e88d25baf2c2414d)<br>HRfix will fallback to half-resolution only.`;
401
+ console.warn(message);
402
+ if (notify)
403
+ notifications.notify(message, {
404
+ type: NotificationType.WARN,
405
+ timeout: config.notificationTimeout * 4,
406
+ });
407
+ // Hide all new hrfix options
408
+ document
409
+ .querySelectorAll(".hrfix")
410
+ .forEach((el) => (el.style.display = "none"));
411
+
412
+ // We are using old HRFix
413
+ global.isOldHRFix = true;
414
+ stableDiffusionData.enable_hr = false;
415
+ }
416
+ switch (response.status) {
417
+ case 200: {
418
+ setConnectionStatus("online");
419
+ // Load data as soon as connection is first stablished
420
+ if (firstTimeOnline) {
421
+ getConfig();
422
+ getStyles();
423
+ getSamplers();
424
+ getUpscalers();
425
+ getModels();
426
+ extensions.getExtensions(
427
+ controlNetModelAutoComplete,
428
+ controlNetModuleAutoComplete,
429
+ controlNetReferenceModuleAutoComplete
430
+ );
431
+ getLoras();
432
+ // getTIEmbeddings();
433
+ // getHypernets();
434
+ firstTimeOnline = false;
435
+ }
436
+ break;
437
+ }
438
+ case 404: {
439
+ apiIssueResult();
440
+ break;
441
+ }
442
+ default: {
443
+ offlineResult();
444
+ }
445
+ }
446
+ }
447
+ } catch (e) {
448
+ try {
449
+ if (e instanceof DOMException) throw "offline";
450
+ // Tests if problem is CORS
451
+ await fetch(url, {mode: "no-cors"});
452
+
453
+ setConnectionStatus("corsissue");
454
+ const message = `CORS is blocking our requests. Try running the webui with the flag '--cors-allow-origins=${window.location.protocol}//${window.location.host}/'`;
455
+ console.error(message);
456
+ if (notify)
457
+ notifications.notify(message, {
458
+ type: NotificationType.ERROR,
459
+ timeout: config.notificationTimeout * 2,
460
+ });
461
+ } catch (e) {
462
+ setConnectionStatus("offline");
463
+ const message = `The server seems to be offline. Is host '${
464
+ document.getElementById("host").value
465
+ }' correct?`;
466
+ console.error(message);
467
+ if (notify)
468
+ notifications.notify(message, {
469
+ type: NotificationType.ERROR,
470
+ timeout: config.notificationTimeout * 2,
471
+ });
472
+ }
473
+ }
474
+ checkInProgress = false;
475
+ return status;
476
+ };
477
+
478
+ if (focused || firstTimeOnline) {
479
+ await checkConnection(!urlParams.has("noprompt"));
480
+ }
481
+
482
+ // On click, attempt to refresh
483
+ connectionIndicator.onclick = async () => {
484
+ try {
485
+ await checkConnection(true);
486
+ checked = true;
487
+ } catch (e) {
488
+ console.debug("Already refreshing");
489
+ }
490
+ };
491
+
492
+ // Checks every 5 seconds if offline, 60 seconds if online
493
+ const checkAgain = () => {
494
+ checkFocus();
495
+ if (focused || firstTimeOnline) {
496
+ setTimeout(
497
+ async () => {
498
+ let simple = !firstTimeOnline;
499
+ await checkConnection(false, simple);
500
+ checkAgain();
501
+ },
502
+ connectionStatus ? 60000 : 5000
503
+ );
504
+ } else {
505
+ setTimeout(() => {
506
+ checkAgain();
507
+ }, 60000);
508
+ }
509
+ };
510
+
511
+ checkAgain();
512
+
513
+ return () => {
514
+ checkConnection().catch(() => {});
515
+ };
516
+ }
517
+
518
+ function newImage(evt) {
519
+ clearPaintedMask();
520
+ uil.layers.forEach(({layer}) => {
521
+ commands.runCommand(
522
+ "eraseImage",
523
+ "Clear Canvas",
524
+ {
525
+ ...layer.bb,
526
+ ctx: layer.ctx,
527
+ },
528
+ {
529
+ extra: {
530
+ log: `Cleared Canvas`,
531
+ },
532
+ }
533
+ );
534
+ });
535
+ }
536
+
537
+ function clearPaintedMask() {
538
+ maskPaintLayer.clear();
539
+ }
540
+
541
+ function march(bb, options = {}) {
542
+ defaultOpt(options, {
543
+ title: null,
544
+ titleStyle: "#FFF5",
545
+ style: "#FFFF",
546
+ width: "2px",
547
+ filter: null,
548
+ });
549
+
550
+ const expanded = {...bb};
551
+ expanded.x--;
552
+ expanded.y--;
553
+ expanded.w += 2;
554
+ expanded.h += 2;
555
+
556
+ // Get temporary layer to draw marching ants
557
+ const layer = imageCollection.registerLayer(null, {
558
+ bb: expanded,
559
+ category: "display",
560
+ });
561
+ layer.canvas.style.imageRendering = "pixelated";
562
+ let offset = 0;
563
+
564
+ const interval = setInterval(() => {
565
+ drawMarchingAnts(layer.ctx, bb, offset++, options);
566
+ offset %= 12;
567
+ }, 20);
568
+
569
+ return () => {
570
+ clearInterval(interval);
571
+ imageCollection.deleteLayer(layer);
572
+ };
573
+ }
574
+
575
+ function drawMarchingAnts(ctx, bb, offset, options) {
576
+ ctx.save();
577
+
578
+ ctx.clearRect(0, 0, bb.w + 2, bb.h + 2);
579
+
580
+ // Draw Tool Name
581
+ if (bb.h > 40 && options.title) {
582
+ ctx.font = `bold 20px Open Sans`;
583
+
584
+ ctx.textAlign = "left";
585
+ ctx.fillStyle = options.titleStyle;
586
+ ctx.fillText(options.title, 10, 30, bb.w);
587
+ }
588
+
589
+ ctx.strokeStyle = options.style;
590
+ ctx.strokeWidth = options.width;
591
+ ctx.filter = options.filter;
592
+ ctx.setLineDash([4, 2]);
593
+ ctx.lineDashOffset = -offset;
594
+ ctx.strokeRect(1, 1, bb.w, bb.h);
595
+
596
+ ctx.restore();
597
+ }
598
+
599
+ const makeSlider = (
600
+ label,
601
+ el,
602
+ lsKey,
603
+ min,
604
+ max,
605
+ step,
606
+ defaultValue,
607
+ textStep = null,
608
+ valuecb = null
609
+ ) => {
610
+ const local = lsKey && localStorage.getItem(`openoutpaint/${lsKey}`);
611
+ const def = parseFloat(local === null ? defaultValue : local);
612
+ let cb = (v) => {
613
+ stableDiffusionData[lsKey] = v;
614
+ if (lsKey) localStorage.setItem(`openoutpaint/${lsKey}`, v);
615
+ };
616
+ if (valuecb) {
617
+ cb = (v) => {
618
+ valuecb(v);
619
+ localStorage.setItem(`openoutpaint/${lsKey}`, v);
620
+ };
621
+ }
622
+ return createSlider(label, el, {
623
+ valuecb: cb,
624
+ min,
625
+ max,
626
+ step,
627
+ defaultValue: def,
628
+ textStep,
629
+ });
630
+ };
631
+
632
+ let modelAutoComplete = createAutoComplete(
633
+ "Model",
634
+ document.getElementById("models-ac-select"),
635
+ {},
636
+ document.getElementById("refreshModelsBtn"),
637
+ "refreshable"
638
+ );
639
+ modelAutoComplete.onchange.on(({value}) => {
640
+ /**
641
+ * TODO implement optional API call to check model unet channel count
642
+ * extension users guaranteed to have it as of
643
+ * https://github.com/zero01101/openOutpaint-webUI-extension/commit/1f22f5ea5b860c6e91f77edfb47743a124596dec
644
+ * but still need a fallback check like below
645
+ */
646
+
647
+ if (value.toLowerCase().includes("inpainting"))
648
+ document.querySelector(
649
+ "#models-ac-select input.autocomplete-text"
650
+ ).style.backgroundColor = "#cfc";
651
+ else
652
+ document.querySelector(
653
+ "#models-ac-select input.autocomplete-text"
654
+ ).style.backgroundColor = "#fcc";
655
+ });
656
+
657
+ let loraAutoComplete = createAutoComplete(
658
+ "LoRa",
659
+ document.getElementById("lora-ac-select")
660
+ );
661
+ loraAutoComplete.onchange.on(({value}) => {
662
+ // add selected lora to the end of the prompt
663
+ let passVal = " <lora:" + value + ":1>";
664
+ let promptInput = document.getElementById("prompt");
665
+ promptInput.value += passVal;
666
+ let promptThing = prompt;
667
+ });
668
+
669
+ const samplerAutoComplete = createAutoComplete(
670
+ "Sampler",
671
+ document.getElementById("sampler-ac-select")
672
+ );
673
+
674
+ const upscalerAutoComplete = createAutoComplete(
675
+ "Upscaler",
676
+ document.getElementById("upscaler-ac-select")
677
+ );
678
+
679
+ const hrFixUpscalerAutoComplete = createAutoComplete(
680
+ "HRfix Upscaler",
681
+ document.getElementById("hrFixUpscaler")
682
+ );
683
+
684
+ let controlNetModelAutoComplete = createAutoComplete(
685
+ "Inpaint Model",
686
+ document.getElementById("controlNetModel-ac-select")
687
+ );
688
+
689
+ controlNetModelAutoComplete.onchange.on(({value}) => {
690
+ extensions.selectedControlNetModel = value;
691
+ });
692
+
693
+ let controlNetModuleAutoComplete = createAutoComplete(
694
+ "Inpaint Preprocessor",
695
+ document.getElementById("controlNetModule-ac-select")
696
+ );
697
+
698
+ controlNetModuleAutoComplete.onchange.on(({value}) => {
699
+ extensions.selectedControlNetModule = value;
700
+ });
701
+
702
+ let controlNetReferenceModuleAutoComplete = createAutoComplete(
703
+ "Reference Preprocessor",
704
+ document.getElementById("controlNetReferenceModule-ac-select")
705
+ );
706
+
707
+ controlNetReferenceModuleAutoComplete.onchange.on(({value}) => {
708
+ extensions.selectedCNReferenceModule = value;
709
+ });
710
+
711
+ // const extensionsAutoComplete = createAutoComplete(
712
+ // "Extension",
713
+ // document.getElementById("extension-ac-select")
714
+ // );
715
+
716
+ hrFixUpscalerAutoComplete.onchange.on(({value}) => {
717
+ stableDiffusionData.hr_upscaler = value;
718
+ localStorage.setItem(`openoutpaint/hr_upscaler`, value);
719
+ });
720
+
721
+ const resSlider = makeSlider(
722
+ "Resolution",
723
+ document.getElementById("resolution"),
724
+ "resolution",
725
+ 128,
726
+ 2048,
727
+ 128,
728
+ 512,
729
+ 2,
730
+ (v) => {
731
+ stableDiffusionData.width = stableDiffusionData.height = v;
732
+
733
+ toolbar.currentTool &&
734
+ toolbar.currentTool.redraw &&
735
+ toolbar.currentTool.redraw();
736
+ }
737
+ );
738
+
739
+ const refSlider = makeSlider(
740
+ "Reference Fidelity",
741
+ document.getElementById("controlNetReferenceFidelity"),
742
+ "cn_reference_fidelity",
743
+ 0.0,
744
+ 1.0,
745
+ 0.1,
746
+ 0.5,
747
+ 0.01,
748
+ (v) => {
749
+ extensions.controlNetReferenceFidelity = v;
750
+
751
+ toolbar.currentTool &&
752
+ toolbar.currentTool.redraw &&
753
+ toolbar.currentTool.redraw();
754
+ }
755
+ );
756
+
757
+ makeSlider(
758
+ "CFG Scale",
759
+ document.getElementById("cfgScale"),
760
+ "cfg_scale",
761
+ localStorage.getItem("openoutpaint/settings.min-cfg") || 1,
762
+ localStorage.getItem("openoutpaint/settings.max-cfg") || 25,
763
+ 0.5,
764
+ 7.0,
765
+ 0.1
766
+ );
767
+ makeSlider(
768
+ "Batch Size",
769
+ document.getElementById("batchSize"),
770
+ "batch_size",
771
+ 1,
772
+ 8,
773
+ 1,
774
+ 2
775
+ );
776
+ makeSlider(
777
+ "Iterations",
778
+ document.getElementById("batchCount"),
779
+ "n_iter",
780
+ 1,
781
+ 8,
782
+ 1,
783
+ 2
784
+ );
785
+ makeSlider(
786
+ "Upscale X",
787
+ document.getElementById("upscaleX"),
788
+ "upscale_x",
789
+ 1.0,
790
+ 4.0,
791
+ 0.1,
792
+ 2.0,
793
+ 0.1
794
+ );
795
+
796
+ makeSlider(
797
+ "Steps",
798
+ document.getElementById("steps"),
799
+ "steps",
800
+ 1,
801
+ localStorage.getItem("openoutpaint/settings.max-steps") || 70,
802
+ 5,
803
+ 30,
804
+ 1
805
+ );
806
+
807
+ // 20230102 grumble grumble
808
+ const hrFixScaleSlider = makeSlider(
809
+ "HRfix Scale",
810
+ document.getElementById("hrFixScale"),
811
+ "hr_scale",
812
+ 1.0,
813
+ 4.0,
814
+ 0.1,
815
+ 2.0,
816
+ 0.1
817
+ );
818
+
819
+ makeSlider(
820
+ "HRfix Denoising",
821
+ document.getElementById("hrDenoising"),
822
+ "hr_denoising_strength",
823
+ 0.0,
824
+ 1.0,
825
+ 0.05,
826
+ 0.7,
827
+ 0.01
828
+ );
829
+
830
+ const lockPxSlider = makeSlider(
831
+ "HRfix Autoscale Lock Px.",
832
+ document.getElementById("hrFixLockPx"),
833
+ "hr_fix_lock_px",
834
+ 0,
835
+ 1024,
836
+ 256,
837
+ 0,
838
+ 1
839
+ );
840
+
841
+ const hrStepsSlider = makeSlider(
842
+ "HRfix Steps",
843
+ document.getElementById("hrFixSteps"),
844
+ "hr_second_pass_steps",
845
+ 0,
846
+ localStorage.getItem("openoutpaint/settings.max-steps") || 70,
847
+ 5,
848
+ 0,
849
+ 1
850
+ );
851
+
852
+ function changeMaskBlur() {
853
+ stableDiffusionData.mask_blur = parseInt(
854
+ document.getElementById("maskBlur").value
855
+ );
856
+ localStorage.setItem("openoutpaint/mask_blur", stableDiffusionData.mask_blur);
857
+ }
858
+
859
+ function changeSeed() {
860
+ stableDiffusionData.seed = document.getElementById("seed").value;
861
+ localStorage.setItem("openoutpaint/seed", stableDiffusionData.seed);
862
+ }
863
+
864
+ function changeHRFX() {
865
+ stableDiffusionData.hr_resize_x =
866
+ document.getElementById("hr_resize_x").value;
867
+ }
868
+
869
+ function changeHRFY() {
870
+ stableDiffusionData.hr_resize_y =
871
+ document.getElementById("hr_resize_y").value;
872
+ }
873
+
874
+ function changeDynamicPromptsExtension() {
875
+ extensions.dynamicPromptsActive =
876
+ document.getElementById("cbxDynPrompts").checked;
877
+ }
878
+
879
+ function changeControlNetExtension() {
880
+ extensions.controlNetActive =
881
+ document.getElementById("cbxControlNet").checked;
882
+ if (extensions.controlNetActive) {
883
+ document
884
+ .querySelectorAll(".controlNetElement")
885
+ .forEach((el) => el.classList.remove("invisible"));
886
+ } else {
887
+ document
888
+ .querySelectorAll(".controlNetElement")
889
+ .forEach((el) => el.classList.add("invisible"));
890
+ }
891
+ changeControlNetReference();
892
+ }
893
+
894
+ function changeControlNetReference() {
895
+ extensions.controlNetReferenceActive = document.getElementById(
896
+ "cbxControlNetReferenceLayer"
897
+ ).checked;
898
+ if (extensions.controlNetReferenceActive && extensions.controlNetActive) {
899
+ document
900
+ .querySelectorAll(".controlNetReferenceElement")
901
+ .forEach((el) => el.classList.remove("invisible"));
902
+ } else {
903
+ document
904
+ .querySelectorAll(".controlNetReferenceElement")
905
+ .forEach((el) => el.classList.add("invisible"));
906
+ }
907
+ }
908
+
909
+ function changeHiResFix() {
910
+ stableDiffusionData.enable_hr = Boolean(
911
+ document.getElementById("cbxHRFix").checked
912
+ );
913
+ localStorage.setItem("openoutpaint/enable_hr", stableDiffusionData.enable_hr);
914
+ // var hrfSlider = document.getElementById("hrFixScale");
915
+ // var hrfOpotions = document.getElementById("hrFixUpscaler");
916
+ // var hrfLabel = document.getElementById("hrFixLabel");
917
+ // var hrfDenoiseSlider = document.getElementById("hrDenoising");
918
+ // var hrfLockPxSlider = document.getElementById("hrFixLockPx");
919
+ if (stableDiffusionData.enable_hr) {
920
+ document
921
+ .querySelectorAll(".hrfix")
922
+ .forEach((el) => el.classList.remove("invisible"));
923
+ } else {
924
+ document
925
+ .querySelectorAll(".hrfix")
926
+ .forEach((el) => el.classList.add("invisible"));
927
+ }
928
+ }
929
+
930
+ function changeHiResSquare() {
931
+ stableDiffusionData.hr_square_aspect = Boolean(
932
+ document.getElementById("cbxHRFSquare").checked
933
+ );
934
+ }
935
+
936
+ function changeRestoreFaces() {
937
+ stableDiffusionData.restore_faces = Boolean(
938
+ document.getElementById("cbxRestoreFaces").checked
939
+ );
940
+ localStorage.setItem(
941
+ "openoutpaint/restore_faces",
942
+ stableDiffusionData.restore_faces
943
+ );
944
+ }
945
+
946
+ function changeSyncCursorSize() {
947
+ global.syncCursorSize = Boolean(
948
+ document.getElementById("cbxSyncCursorSize").checked
949
+ );
950
+ localStorage.setItem("openoutpaint/sync_cursor_size", global.syncCursorSize);
951
+ }
952
+
953
+ function changeSmoothRendering() {
954
+ const layers = document.getElementById("layer-render");
955
+ if (localStorage.getItem("openoutpaint/settings.smooth") === "true") {
956
+ layers.classList.remove("pixelated");
957
+ } else {
958
+ layers.classList.add("pixelated");
959
+ }
960
+ }
961
+
962
+ function isCanvasBlank(x, y, w, h, canvas) {
963
+ return !canvas
964
+ .getContext("2d")
965
+ .getImageData(x, y, w, h)
966
+ .data.some((channel) => channel !== 0);
967
+ }
968
+
969
+ function drawBackground() {
970
+ {
971
+ // Existing Canvas BG
972
+ const canvas = document.createElement("canvas");
973
+ canvas.width = config.gridSize * 2;
974
+ canvas.height = config.gridSize * 2;
975
+
976
+ const ctx = canvas.getContext("2d");
977
+ ctx.fillStyle = theme.grid.dark;
978
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
979
+ ctx.fillStyle = theme.grid.light;
980
+ ctx.fillRect(0, 0, config.gridSize, config.gridSize);
981
+ ctx.fillRect(
982
+ config.gridSize,
983
+ config.gridSize,
984
+ config.gridSize,
985
+ config.gridSize
986
+ );
987
+
988
+ canvas.toBlob((blob) => {
989
+ const url = window.URL.createObjectURL(blob);
990
+ console.debug(url);
991
+ bgLayer.canvas.style.backgroundImage = `url(${url})`;
992
+ });
993
+ }
994
+ }
995
+
996
+ async function exportWorkspaceState() {
997
+ return {
998
+ defaultLayer: {
999
+ id: uil.layerIndex.default.id,
1000
+ name: uil.layerIndex.default.name,
1001
+ },
1002
+ bb: {
1003
+ x: imageCollection.bb.x,
1004
+ y: imageCollection.bb.y,
1005
+ w: imageCollection.bb.w,
1006
+ h: imageCollection.bb.h,
1007
+ },
1008
+ history: await commands.export(),
1009
+ };
1010
+ }
1011
+
1012
+ async function importWorkspaceState(state) {
1013
+ // Start from zero, effectively
1014
+ await commands.clear();
1015
+
1016
+ // Setup initial layer
1017
+ const layer = uil.layerIndex.default;
1018
+ layer.deletable = true;
1019
+
1020
+ await commands.runCommand(
1021
+ "addLayer",
1022
+ "Temporary Layer",
1023
+ {name: "Temporary Layer", key: "tmp"},
1024
+ {recordHistory: false}
1025
+ );
1026
+
1027
+ await commands.runCommand(
1028
+ "deleteLayer",
1029
+ "Deleted Layer",
1030
+ {
1031
+ layer,
1032
+ },
1033
+ {recordHistory: false}
1034
+ );
1035
+
1036
+ await commands.runCommand(
1037
+ "addLayer",
1038
+ "Initial Layer Creation",
1039
+ {
1040
+ id: state.defaultLayer.id,
1041
+ name: state.defaultLayer.name,
1042
+ key: "default",
1043
+ deletable: false,
1044
+ },
1045
+ {recordHistory: false}
1046
+ );
1047
+
1048
+ await commands.runCommand(
1049
+ "deleteLayer",
1050
+ "Deleted Layer",
1051
+ {
1052
+ layer: uil.layerIndex.tmp,
1053
+ },
1054
+ {recordHistory: false}
1055
+ );
1056
+
1057
+ // Resize canvas to match original size
1058
+ const sbb = new BoundingBox(state.bb);
1059
+
1060
+ const bb = imageCollection.bb;
1061
+ let eleft = 0;
1062
+ if (bb.x > sbb.x) eleft = bb.x - sbb.x;
1063
+ let etop = 0;
1064
+ if (bb.y > sbb.y) etop = bb.y - sbb.y;
1065
+
1066
+ let eright = 0;
1067
+ if (bb.tr.x < sbb.tr.x) eright = sbb.tr.x - bb.tr.x;
1068
+ let ebottom = 0;
1069
+ if (bb.br.y < sbb.br.y) ebottom = sbb.br.y - bb.br.y;
1070
+
1071
+ imageCollection.expand(eleft, etop, eright, ebottom);
1072
+
1073
+ // Run commands in order
1074
+ for (const command of state.history) {
1075
+ await commands.import(command);
1076
+ }
1077
+ }
1078
+
1079
+ async function saveWorkspaceToFile() {
1080
+ const workspace = await exportWorkspaceState();
1081
+
1082
+ const blob = new Blob([JSON.stringify(workspace)], {
1083
+ type: "application/json",
1084
+ });
1085
+
1086
+ const url = URL.createObjectURL(blob);
1087
+ var link = document.createElement("a"); // Or maybe get it from the current document
1088
+ link.href = url;
1089
+ link.download = `${new Date().toISOString()}_openOutpaint_workspace.json`;
1090
+ link.click();
1091
+ }
1092
+
1093
+ async function getUpscalers() {
1094
+ var url = document.getElementById("host").value + "/sdapi/v1/upscalers";
1095
+ let upscalers = [];
1096
+
1097
+ try {
1098
+ const response = await fetch(url, {
1099
+ method: "GET",
1100
+ headers: {
1101
+ Accept: "application/json",
1102
+ "Content-Type": "application/json",
1103
+ },
1104
+ });
1105
+ const data = await response.json();
1106
+ for (var i = 0; i < data.length; i++) {
1107
+ if (data[i].name.includes("None")) {
1108
+ continue;
1109
+ }
1110
+ upscalers.push(data[i].name);
1111
+ }
1112
+ } catch (e) {
1113
+ console.warn("[index] Failed to fetch upscalers:");
1114
+ console.warn(e);
1115
+ upscalers = [
1116
+ "Lanczos",
1117
+ "Nearest",
1118
+ "LDSR",
1119
+ "SwinIR",
1120
+ "R-ESRGAN General 4xV3",
1121
+ "R-ESRGAN General WDN 4xV3",
1122
+ "R-ESRGAN AnimeVideo",
1123
+ "R-ESRGAN 4x+",
1124
+ "R-ESRGAN 4x+ Anime6B",
1125
+ "R-ESRGAN 2x+",
1126
+ ];
1127
+ }
1128
+ const upscalersPlusNone = [...upscalers];
1129
+ upscalersPlusNone.unshift("None");
1130
+ upscalersPlusNone.push("Latent");
1131
+ upscalersPlusNone.push("Latent (antialiased)");
1132
+ upscalersPlusNone.push("Latent (bicubic)");
1133
+ upscalersPlusNone.push("Latent (bicubic, antialiased)");
1134
+ upscalersPlusNone.push("Latent (nearest)");
1135
+
1136
+ upscalerAutoComplete.options = upscalers.map((u) => {
1137
+ return {name: u, value: u};
1138
+ });
1139
+ hrFixUpscalerAutoComplete.options = upscalersPlusNone.map((u) => {
1140
+ return {name: u, value: u};
1141
+ });
1142
+
1143
+ upscalerAutoComplete.value = upscalers[0];
1144
+ hrFixUpscalerAutoComplete.value =
1145
+ localStorage.getItem("openoutpaint/hr_upscaler") === null
1146
+ ? "None"
1147
+ : localStorage.getItem("openoutpaint/hr_upscaler");
1148
+ }
1149
+
1150
+ async function getModels(refresh = false) {
1151
+ const url = document.getElementById("host").value + "/sdapi/v1/sd-models";
1152
+ let opt = null;
1153
+
1154
+ try {
1155
+ const response = await fetch(url);
1156
+ const data = await response.json();
1157
+
1158
+ opt = data.map((option) => ({
1159
+ name: option.title,
1160
+ value: option.title,
1161
+ optionelcb: (el) => {
1162
+ if (option.title.toLowerCase().includes("inpainting"))
1163
+ el.classList.add("inpainting");
1164
+ },
1165
+ }));
1166
+
1167
+ modelAutoComplete.options = opt;
1168
+
1169
+ try {
1170
+ const optResponse = await fetch(
1171
+ document.getElementById("host").value + "/sdapi/v1/options"
1172
+ );
1173
+ const optData = await optResponse.json();
1174
+
1175
+ var model = optData.sd_model_checkpoint;
1176
+ // 20230722 - sigh so this key is now removed https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/66c5f1bb1556a2d86d9f11aeb92f83d4a09832cc
1177
+ // no idea why but time to deal with it
1178
+ if (model === undefined) {
1179
+ const modelHash = optData.sd_checkpoint_hash;
1180
+ const hashMap = data.map((option) => ({
1181
+ hash: option.sha256,
1182
+ title: option.title,
1183
+ }));
1184
+ model = hashMap.find((option) => option.hash === modelHash).title;
1185
+ }
1186
+ console.log("Current model: " + model);
1187
+ if (modelAutoComplete.value !== model) modelAutoComplete.value = model;
1188
+ } catch (e) {
1189
+ console.warn("[index] Failed to fetch current model:");
1190
+ console.warn(e);
1191
+ }
1192
+ } catch (e) {
1193
+ console.warn("[index] Failed to fetch models:");
1194
+ console.warn(e);
1195
+ }
1196
+
1197
+ if (!refresh)
1198
+ modelAutoComplete.onchange.on(async ({value}) => {
1199
+ console.log(`[index] Changing model to [${value}]`);
1200
+ const payload = {
1201
+ sd_model_checkpoint: value,
1202
+ };
1203
+ const url = document.getElementById("host").value + "/sdapi/v1/options/";
1204
+ try {
1205
+ await fetch(url, {
1206
+ method: "POST",
1207
+ headers: {
1208
+ "Content-Type": "application/json",
1209
+ },
1210
+ body: JSON.stringify(payload),
1211
+ });
1212
+
1213
+ notifications.notify(`Model changed to [${value}]`, {type: "success"});
1214
+ } catch (e) {
1215
+ console.warn("[index] Error changing model");
1216
+ console.warn(e);
1217
+
1218
+ notifications.notify(
1219
+ "Error changing model, please check console for additional information",
1220
+ {
1221
+ type: NotificationType.ERROR,
1222
+ timeout: config.notificationTimeout * 2,
1223
+ }
1224
+ );
1225
+ }
1226
+ });
1227
+
1228
+ // If first time running, ask if user wants to switch to an inpainting model
1229
+ if (global.firstRun && !modelAutoComplete.value.includes("inpainting")) {
1230
+ const inpainting = opt.find(({name}) => name.includes("inpainting"));
1231
+
1232
+ let message =
1233
+ "It seems this is your first time using openOutpaint. It is highly recommended that you switch to an inpainting model. \
1234
+ These are highlighted as green in the model selector.";
1235
+
1236
+ if (inpainting) {
1237
+ message += `<br><br>We have found the inpainting model<br><br> - ${inpainting.name}<br><br>available in the webui. Do you want to switch to it?`;
1238
+ if (await notifications.dialog("Automatic Model Switch", message)) {
1239
+ modelAutoComplete.value = inpainting.value;
1240
+ }
1241
+ } else {
1242
+ message += `<br><br>No inpainting model seems to be available in the webui. It is recommended that you download an inpainting model, or outpainting results may not be optimal.`;
1243
+ notifications.notify(message, {
1244
+ type: NotificationType.WARN,
1245
+ timeout: null,
1246
+ });
1247
+ }
1248
+ }
1249
+ }
1250
+
1251
+ async function getLoras() {
1252
+ var url = document.getElementById("host").value + "/sdapi/v1/loras";
1253
+ let opt = null;
1254
+
1255
+ try {
1256
+ const response = await fetch(url);
1257
+ const data = await response.json();
1258
+
1259
+ loraAutoComplete.options = data.map((lora) => ({
1260
+ name: lora.name,
1261
+ value: lora.name,
1262
+ }));
1263
+ } catch (e) {
1264
+ console.warn("[index] Failed to fetch loras");
1265
+ console.warn(e);
1266
+ }
1267
+ }
1268
+
1269
+ async function getConfig() {
1270
+ var url = document.getElementById("host").value + "/sdapi/v1/options";
1271
+
1272
+ let message =
1273
+ "The following options for the AUTOMATIC1111's webui are not recommended to use with this software:";
1274
+
1275
+ try {
1276
+ const response = await fetch(url);
1277
+
1278
+ const data = await response.json();
1279
+
1280
+ let wrong = false;
1281
+
1282
+ // Check if img2img color correction is disabled and inpainting mask weight is set to one
1283
+ // TODO: API Seems bugged for retrieving inpainting mask weight - returning 0 for all values different than 1.0
1284
+ if (data.img2img_color_correction) {
1285
+ message += "<br> - Image to Image Color Correction: false recommended";
1286
+ wrong = true;
1287
+ }
1288
+
1289
+ if (data.inpainting_mask_weight < 1.0) {
1290
+ message += `<br> - Inpainting Conditioning Mask Strength: 1.0 recommended`;
1291
+ wrong = true;
1292
+ }
1293
+
1294
+ message +=
1295
+ "<br><br>Should these values be changed to the recommended ones?";
1296
+
1297
+ if (!wrong) {
1298
+ console.info("[index] WebUI Settings set as recommended.");
1299
+ return;
1300
+ }
1301
+
1302
+ console.info(
1303
+ "[index] WebUI Settings not set as recommended. Prompting for changing settings automatically."
1304
+ );
1305
+
1306
+ if (!(await notifications.dialog("Recommended Settings", message))) return;
1307
+
1308
+ try {
1309
+ await fetch(url, {
1310
+ method: "POST",
1311
+ headers: {
1312
+ "Content-Type": "application/json",
1313
+ },
1314
+ body: JSON.stringify({
1315
+ img2img_color_correction: false,
1316
+ inpainting_mask_weight: 1.0,
1317
+ }),
1318
+ });
1319
+ } catch (e) {
1320
+ console.warn("[index] Failed to fetch WebUI Configuration");
1321
+ console.warn(e);
1322
+ }
1323
+ } catch (e) {
1324
+ console.warn("[index] Failed to fetch WebUI Configuration");
1325
+ console.warn(e);
1326
+ }
1327
+ }
1328
+
1329
+ function changeStyles() {
1330
+ /** @type {HTMLSelectElement} */
1331
+ const styleSelectEl = document.getElementById("styleSelect");
1332
+ const selected = Array.from(styleSelectEl.options).filter(
1333
+ (option) => option.selected
1334
+ );
1335
+ let selectedString = selected.map((option) => option.value);
1336
+
1337
+ if (selectedString.find((selected) => selected === "None")) {
1338
+ selectedString = [];
1339
+ Array.from(styleSelectEl.options).forEach((option) => {
1340
+ if (option.value !== "None") option.selected = false;
1341
+ });
1342
+ }
1343
+
1344
+ localStorage.setItem(
1345
+ "openoutpaint/promptStyle",
1346
+ JSON.stringify(selectedString)
1347
+ );
1348
+
1349
+ // change the model
1350
+ if (selectedString.length > 0)
1351
+ console.log(`[index] Changing styles to ${selectedString.join(", ")}`);
1352
+ else console.log(`[index] Clearing styles`);
1353
+ stableDiffusionData.styles = selectedString;
1354
+ }
1355
+
1356
+ async function getSamplers() {
1357
+ var url = document.getElementById("host").value + "/sdapi/v1/samplers";
1358
+
1359
+ try {
1360
+ const response = await fetch(url);
1361
+ const data = await response.json();
1362
+
1363
+ samplerAutoComplete.onchange.on(({value}) => {
1364
+ stableDiffusionData.sampler_index = value;
1365
+ localStorage.setItem("openoutpaint/sampler", value);
1366
+ });
1367
+
1368
+ samplerAutoComplete.options = data.map((sampler) => ({
1369
+ name: sampler.name,
1370
+ value: sampler.name,
1371
+ }));
1372
+
1373
+ // Initial sampler
1374
+ if (localStorage.getItem("openoutpaint/sampler") != null) {
1375
+ samplerAutoComplete.value = localStorage.getItem("openoutpaint/sampler");
1376
+ } else {
1377
+ samplerAutoComplete.value = data[0].name;
1378
+ localStorage.setItem("openoutpaint/sampler", samplerAutoComplete.value);
1379
+ }
1380
+ stableDiffusionData.sampler_index = samplerAutoComplete.value;
1381
+ } catch (e) {
1382
+ console.warn("[index] Failed to fetch samplers");
1383
+ console.warn(e);
1384
+ }
1385
+ }
1386
+
1387
+ async function upscaleAndDownload() {
1388
+ // Future improvements: some upscalers take a while to upscale, so we should show a loading bar or something, also a slider for the upscale amount
1389
+
1390
+ // get cropped canvas, send it to upscaler, download result
1391
+ var upscale_factor = localStorage.getItem("openoutpaint/upscale_x")
1392
+ ? localStorage.getItem("openoutpaint/upscale_x")
1393
+ : 2;
1394
+ var upscaler = upscalerAutoComplete.value;
1395
+ var croppedCanvas = cropCanvas(
1396
+ uil.getVisible({
1397
+ x: 0,
1398
+ y: 0,
1399
+ w: imageCollection.size.w,
1400
+ h: imageCollection.size.h,
1401
+ })
1402
+ );
1403
+ if (croppedCanvas != null) {
1404
+ var url =
1405
+ document.getElementById("host").value + "/sdapi/v1/extra-single-image/";
1406
+ var imgdata = croppedCanvas.canvas.toDataURL("image/png");
1407
+ var data = {
1408
+ "resize-mode": 0, // 0 = just resize, 1 = crop and resize, 2 = resize and fill i assume based on theimg2img tabs options
1409
+ upscaling_resize: upscale_factor,
1410
+ upscaler_1: upscaler,
1411
+ image: imgdata,
1412
+ };
1413
+ console.log(data);
1414
+ await fetch(url, {
1415
+ method: "POST",
1416
+ headers: {
1417
+ Accept: "application/json",
1418
+ "Content-Type": "application/json",
1419
+ },
1420
+ body: JSON.stringify(data),
1421
+ })
1422
+ .then((response) => response.json())
1423
+ .then((data) => {
1424
+ console.log(data);
1425
+ var link = document.createElement("a");
1426
+ link.download =
1427
+ new Date()
1428
+ .toISOString()
1429
+ .slice(0, 19)
1430
+ .replace("T", " ")
1431
+ .replace(":", " ") +
1432
+ " openOutpaint image upscaler_" +
1433
+ upscaler +
1434
+ "_x" +
1435
+ upscale_factor +
1436
+ ".png";
1437
+ link.href = "data:image/png;base64," + data["image"];
1438
+ link.click();
1439
+ });
1440
+ }
1441
+ }
1442
+
1443
+ function loadSettings() {
1444
+ // set default values if not set
1445
+ var _mask_blur =
1446
+ localStorage.getItem("openoutpaint/mask_blur") == null
1447
+ ? 0
1448
+ : localStorage.getItem("openoutpaint/mask_blur");
1449
+ var _seed =
1450
+ localStorage.getItem("openoutpaint/seed") == null
1451
+ ? -1
1452
+ : localStorage.getItem("openoutpaint/seed");
1453
+ let _enable_hr =
1454
+ localStorage.getItem("openoutpaint/enable_hr") === null
1455
+ ? false
1456
+ : localStorage.getItem("openoutpaint/enable_hr") === "true";
1457
+ let _restore_faces =
1458
+ localStorage.getItem("openoutpaint/restore_faces") === null
1459
+ ? false
1460
+ : localStorage.getItem("openoutpaint/restore_faces") === "true";
1461
+
1462
+ let _sync_cursor_size =
1463
+ localStorage.getItem("openoutpaint/sync_cursor_size") === null
1464
+ ? true
1465
+ : localStorage.getItem("openoutpaint/sync_cursor_size") === "true";
1466
+
1467
+ let _hrfix_scale =
1468
+ localStorage.getItem("openoutpaint/hr_scale") === null
1469
+ ? 2.0
1470
+ : localStorage.getItem("openoutpaint/hr_scale");
1471
+
1472
+ let _hrfix_denoising =
1473
+ localStorage.getItem("openoutpaint/hr_denoising_strength") === null
1474
+ ? 0.7
1475
+ : localStorage.getItem("openoutpaint/hr_denoising_strength");
1476
+ let _hrfix_lock_px =
1477
+ localStorage.getItem("openoutpaint/hr_fix_lock_px") === null
1478
+ ? 0
1479
+ : localStorage.getItem("openoutpaint/hr_fix_lock_px");
1480
+
1481
+ // set the values into the UI
1482
+ document.getElementById("maskBlur").value = Number(_mask_blur);
1483
+ document.getElementById("seed").value = Number(_seed);
1484
+ document.getElementById("cbxHRFix").checked = Boolean(_enable_hr);
1485
+ document.getElementById("cbxRestoreFaces").checked = Boolean(_restore_faces);
1486
+ document.getElementById("cbxSyncCursorSize").checked =
1487
+ Boolean(_sync_cursor_size);
1488
+ document.getElementById("hrFixScale").value = Number(_hrfix_scale);
1489
+ document.getElementById("hrDenoising").value = Number(_hrfix_denoising);
1490
+ document.getElementById("hrFixLockPx").value = Number(_hrfix_lock_px);
1491
+ }
1492
+
1493
+ imageCollection.element.addEventListener(
1494
+ "wheel",
1495
+ (evn) => {
1496
+ evn.preventDefault();
1497
+ },
1498
+ {passive: false}
1499
+ );
1500
+
1501
+ imageCollection.element.addEventListener(
1502
+ "contextmenu",
1503
+ (evn) => {
1504
+ evn.preventDefault();
1505
+ },
1506
+ {passive: false}
1507
+ );
1508
+
1509
+ async function resetToDefaults() {
1510
+ if (
1511
+ await notifications.dialog(
1512
+ "Clear Settings",
1513
+ "Are you sure you want to clear your settings?"
1514
+ )
1515
+ ) {
1516
+ localStorage.clear();
1517
+ }
1518
+ }
1519
+
1520
+ document.addEventListener("visibilitychange", () => {
1521
+ checkFocus();
1522
+ });
1523
+
1524
+ window.addEventListener("blur", () => {
1525
+ checkFocus();
1526
+ });
1527
+
1528
+ window.addEventListener("focus", () => {
1529
+ checkFocus();
1530
+ });
1531
+
1532
+ function checkFocus() {
1533
+ let hasFocus = document.hasFocus();
1534
+ if (document.hidden || !hasFocus) {
1535
+ focused = false;
1536
+ } else {
1537
+ focused = true;
1538
+ }
1539
+ }
1540
+
1541
+ function refreshScripts() {
1542
+ selector = document.getElementById("script-selector");
1543
+ selector.innerHTML = "";
1544
+ createBaseScriptOptions();
1545
+ loadDefaultScripts();
1546
+ // loadUserScripts();
1547
+ }
1548
+
1549
+ function createBaseScriptOptions() {
1550
+ selector = document.getElementById("script-selector");
1551
+ var noScript = document.createElement("option");
1552
+ noScript.id = "no_selected_script";
1553
+ noScript.value = "";
1554
+ noScript.innerHTML = "(disabled)";
1555
+ selector.appendChild(noScript);
1556
+ var customScript = document.createElement("option");
1557
+ customScript.id = "custom";
1558
+ customScript.value = "custom";
1559
+ customScript.innerHTML = "Custom";
1560
+ selector.appendChild(customScript);
1561
+ }
1562
+
1563
+ async function loadDefaultScripts() {
1564
+ selector = document.getElementById("script-selector");
1565
+ const response = await fetch("./defaultscripts.json");
1566
+ const json = await response.json();
1567
+ for (const key in json.defaultScripts) {
1568
+ var opt = document.createElement("option");
1569
+ opt.value = opt.innerHTML = key;
1570
+ selector.appendChild(opt);
1571
+ }
1572
+ defaultScripts = json;
1573
+ }
1574
+
1575
+ // async function loadUserScripts() {
1576
+ // selector = document.getElementById("script-selector");
1577
+ // const response = await fetch("./userdefinedscripts.json");
1578
+ // const json = await response.json();
1579
+ // for (const key in json.userScripts) {
1580
+ // var opt = document.createElement("option");
1581
+ // opt.value = opt.innerHTML = key;
1582
+ // selector.appendChild(opt);
1583
+ // }
1584
+ // userScripts = json;
1585
+ // }
1586
+
1587
+ function changeScript(event) {
1588
+ let enable = () => {
1589
+ scriptName.disabled = false;
1590
+ // saveScriptButton.disabled = false;
1591
+ };
1592
+ let disable = () => {
1593
+ scriptName.disabled = true;
1594
+ // saveScriptButton.disabled = true;
1595
+ };
1596
+ let selected = event.target.value;
1597
+ let scriptName = document.getElementById("script-name-input");
1598
+ let scriptArgs = document.getElementById("script-args-input");
1599
+ // let saveScriptButton = document.getElementById("save-custom-script");
1600
+ scriptName.value = selected;
1601
+ scriptArgs.title = "";
1602
+ disable();
1603
+ switch (selected) {
1604
+ case "custom": {
1605
+ let _script_name_input =
1606
+ localStorage.getItem("openoutpaint/script_name_input") === null
1607
+ ? ""
1608
+ : localStorage.getItem("openoutpaint/script_name_input");
1609
+ let _script_args_input =
1610
+ localStorage.getItem("openoutpaint/script_args_input") === null
1611
+ ? "[]"
1612
+ : localStorage.getItem("openoutpaint/script_args_input");
1613
+ scriptName.value = _script_name_input;
1614
+ scriptArgs.value = _script_args_input;
1615
+ scriptArgs.title = "";
1616
+ enable();
1617
+ break;
1618
+ }
1619
+ case "": {
1620
+ // specifically no selected script
1621
+ scriptArgs.value = "";
1622
+ break;
1623
+ }
1624
+ default: {
1625
+ scriptName.value = selected;
1626
+ // check default scripts for selected script
1627
+ if (selected in defaultScripts.defaultScripts) {
1628
+ scriptArgs.value = defaultScripts.defaultScripts[selected].scriptValues;
1629
+ scriptArgs.title = defaultScripts.defaultScripts[selected].titleText;
1630
+ }
1631
+ // FURTHER TODO see if this is even plausible as i don't think JS can arbitrarily save data to files without downloading
1632
+
1633
+ // if not found, check user scripts
1634
+ // TODO yknow what check userscripts first; if customizations have been made load those instead of defaults, i'm too stupid to do that right now
1635
+ // else if (selected in userScripts.userScripts) {
1636
+ // scriptArgs.value = userScripts.userScripts[selected].scriptValues;
1637
+ // enable();
1638
+ // }
1639
+ // if not found, wtf
1640
+ }
1641
+ }
1642
+ }
1643
+
1644
+ // async function saveCustomScript() {
1645
+ // let selector = document.getElementById("script-name-input");
1646
+ // let selected = selector.value;
1647
+ // let args = document.getElementById("script-args-input").value;
1648
+ // if (selected.trim() != "") {
1649
+ // if (selected in userScripts.userScripts) {
1650
+ // userScripts.userScripts[selected].scriptValues = args;
1651
+ // } else {
1652
+ // }
1653
+ // }
1654
+ // }
1655
+
1656
+ function togglePix2PixImgCfg(value) {
1657
+ // super hacky
1658
+ // actually doesn't work at all yet so i'm leaving it here to taunt and remind me of my failures
1659
+ // try {
1660
+ // if (value.toLowerCase().includes("pix2pix")) {
1661
+ // document
1662
+ // .querySelector(".instruct-pix2pix-img-cfg")
1663
+ // .classList.remove("invisible");
1664
+ // } else {
1665
+ // document
1666
+ // .querySelector(".instruct-pix2pix-img-cfg")
1667
+ // .classList.add("invisible");
1668
+ // }
1669
+ // } catch (e) {
1670
+ // // highly likely not currently using img2img tool, do nothing
1671
+ // }
1672
+ }
1673
+
1674
+ function storeUserscriptVal(evt, type) {
1675
+ let currentScript = document.getElementById("script-selector").value;
1676
+ if (currentScript === "custom") {
1677
+ console.log(type);
1678
+ console.log(evt);
1679
+ let val = (currentScript = document.getElementById(
1680
+ "script-" + type + "-input"
1681
+ ).value);
1682
+
1683
+ localStorage.setItem("openoutpaint/script_" + type + "_input", val);
1684
+ }
1685
+ }
extensions/openOutpaint-webUI-extension/app/js/initalize/debug.populate.js ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // info div, sometimes hidden
2
+ let mouseXInfo = document.getElementById("mouseX");
3
+ let mouseYInfo = document.getElementById("mouseY");
4
+ let canvasXInfo = document.getElementById("canvasX");
5
+ let canvasYInfo = document.getElementById("canvasY");
6
+ let snapXInfo = document.getElementById("snapX");
7
+ let snapYInfo = document.getElementById("snapY");
8
+ let heldButtonInfo = document.getElementById("heldButton");
9
+
10
+ mouse.listen.window.onmousemove.on((evn) => {
11
+ mouseXInfo.textContent = evn.x;
12
+ mouseYInfo.textContent = evn.y;
13
+ });
14
+
15
+ mouse.listen.world.onmousemove.on((evn) => {
16
+ canvasXInfo.textContent = evn.x;
17
+ canvasYInfo.textContent = evn.y;
18
+ snapXInfo.textContent = evn.x + snap(evn.x);
19
+ snapYInfo.textContent = evn.y + snap(evn.y);
20
+
21
+ if (global.debug) {
22
+ debugLayer.clear();
23
+ debugCtx.fillStyle = "#F0F";
24
+ debugCtx.beginPath();
25
+ debugCtx.arc(viewport.cx, viewport.cy, 5, 0, Math.PI * 2);
26
+ debugCtx.fill();
27
+
28
+ debugCtx.fillStyle = "#0FF";
29
+ debugCtx.beginPath();
30
+ debugCtx.arc(evn.x, evn.y, 5, 0, Math.PI * 2);
31
+ debugCtx.fill();
32
+ }
33
+ });