diff --git a/.devtools/README.md b/.devtools/README.md new file mode 100644 index 0000000..22752a2 --- /dev/null +++ b/.devtools/README.md @@ -0,0 +1,12 @@ +# openOutpaint DevTools + +This is a folder containing some handy scripts to help developers to automate workflows and write code in openOutpaint's standards. +All scripts must be run from the root of the project. + +## `sethooks.sh` script + +This script 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. + +## `lint.sh` script + +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. diff --git a/lint.sh b/.devtools/lint.sh old mode 100644 new mode 100755 similarity index 100% rename from lint.sh rename to .devtools/lint.sh diff --git a/.devtools/sethooks.sh b/.devtools/sethooks.sh new file mode 100755 index 0000000..7df28b7 --- /dev/null +++ b/.devtools/sethooks.sh @@ -0,0 +1,3 @@ +#!/usr/bin/sh + +git config core.hooksPath .githooks \ No newline at end of file diff --git a/.devtools/updatehashes.sh b/.devtools/updatehashes.sh new file mode 100644 index 0000000..372b37f --- /dev/null +++ b/.devtools/updatehashes.sh @@ -0,0 +1,121 @@ +#!/usr/bin/bash +# +# Updates html files with cache busting urls including file hashes. + +# Setup colors +# Reset +Color_Off='\033[0m' # Text Reset + +# Regular Colors +Black='\033[0;30m' # Black +Red='\033[0;31m' # Red +Green='\033[0;32m' # Green +Yellow='\033[0;33m' # Yellow +Blue='\033[0;34m' # Blue +Purple='\033[0;35m' # Purple +Cyan='\033[0;36m' # Cyan +White='\033[0;37m' # White + +# Bold +BBlack='\033[1;30m' # Black +BRed='\033[1;31m' # Red +BGreen='\033[1;32m' # Green +BYellow='\033[1;33m' # Yellow +BBlue='\033[1;34m' # Blue +BPurple='\033[1;35m' # Purple +BCyan='\033[1;36m' # Cyan +BWhite='\033[1;37m' # White + +# Underline +UBlack='\033[4;30m' # Black +URed='\033[4;31m' # Red +UGreen='\033[4;32m' # Green +UYellow='\033[4;33m' # Yellow +UBlue='\033[4;34m' # Blue +UPurple='\033[4;35m' # Purple +UCyan='\033[4;36m' # Cyan +UWhite='\033[4;37m' # White + +# Background +On_Black='\033[40m' # Black +On_Red='\033[41m' # Red +On_Green='\033[42m' # Green +On_Yellow='\033[43m' # Yellow +On_Blue='\033[44m' # Blue +On_Purple='\033[45m' # Purple +On_Cyan='\033[46m' # Cyan +On_White='\033[47m' # White + +# High Intensity +IBlack='\033[0;90m' # Black +IRed='\033[0;91m' # Red +IGreen='\033[0;92m' # Green +IYellow='\033[0;93m' # Yellow +IBlue='\033[0;94m' # Blue +IPurple='\033[0;95m' # Purple +ICyan='\033[0;96m' # Cyan +IWhite='\033[0;97m' # White + +# Bold High Intensity +BIBlack='\033[1;90m' # Black +BIRed='\033[1;91m' # Red +BIGreen='\033[1;92m' # Green +BIYellow='\033[1;93m' # Yellow +BIBlue='\033[1;94m' # Blue +BIPurple='\033[1;95m' # Purple +BICyan='\033[1;96m' # Cyan +BIWhite='\033[1;97m' # White + +# High Intensity backgrounds +On_IBlack='\033[0;100m' # Black +On_IRed='\033[0;101m' # Red +On_IGreen='\033[0;102m' # Green +On_IYellow='\033[0;103m' # Yellow +On_IBlue='\033[0;104m' # Blue +On_IPurple='\033[0;105m' # Purple +On_ICyan='\033[0;106m' # Cyan +On_IWhite='\033[0;107m' # White + +# Check requirements +if ! which echo > /dev/null +then + exit -1 +fi + +required_programs=(find grep cut sed sha1sum) + +for program in $required_programs +do + if ! which $program > /dev/null + then + echo -e "${Red}[error] Requires '$program' command to be installed${Color_Off}" + exit -1 + fi +done + +# Actual file processing +for htmlfile in $(find -type f -name \*.html) +do + echo -e "${BIBlue}[info] Processing '${htmlfile}' for cache busting...${Color_Off}" + + for resourcefile in $(find -type f -regex '.*\.css\|.*\.js' | sed 's/\.\///g') + do + # Check if resource is used in html file + resourceusage=$(grep -i "$resourcefile" "$htmlfile") + if [ $? -eq 0 ] + then + # This is just for cache busting... + # If 7 first characters of SHA1 is okay for git, it should be more than enough for us + hash="$(sha1sum $resourcefile | cut -d' ' -f1 | head -c 7)" + + # Check if resource hash is already correct + if ! echo "$resourceusage" | grep -i "=$hash\"" > /dev/null + then + escaped=$(echo $resourcefile | sed 's/\//\\\//g' | sed 's/\./\\./g') + sed -Ei "s/${escaped}(\?v=[a-z0-9]+)?/${escaped}?v=${hash}/g" "$htmlfile" + + echo -e "${BIBlue}[info]${Color_Off} Updated resource ${resourcefile} to hash ${hash}" + fi + fi + done +done \ No newline at end of file diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..1b2e84a --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,9 @@ +#!/bin/sh +# +# Script to perform some basic operations to the code before committing. + +# Adds file hashes to html script imports for cache busting purposes +sh .devtools/updatehashes.sh + +# Adds file to current commit +git add --all \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 612f1b2..b7a9589 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -23,12 +23,15 @@ A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. -**Desktop (please complete the following information):** +**Environment (please complete the following information):** - OS and Version: [e.g. iOS 15, win10x64 v22h2, palmOS 3] - GPU: [e.g. GTX1660, RTX3090, RX750, Voodoo2] -- Browser: [e.g. chrome, safari] -- Version: [e.g. 22] +- Browser and Version: [e.g. chrome 108, safari 16.1] +- Any browser extensions: [rationale: [microsoft editor chrome addon hates overmask](https://github.com/zero01101/openOutpaint/discussions/88#discussioncomment-4498341)] +- Commit of openOutpaint: [e.g. 3d29847, https://github.com/zero01101/openOutpaint/commit/b9fcc7ad00be46f05dd6b54cfac7c05904c84f87] +- Commit of A1111 webUI: [e.g. c5bdba2, https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/5f1dfbbc959855fd90ba80c0c76301d2063772fa] +- How you interact with A1111 webUI: [e.g. local hardware, colab, cloud host like linode] **Additional context** Add any other context about the problem here. diff --git a/.github/workflows/cachebusting.yml b/.github/workflows/cachebusting.yml new file mode 100644 index 0000000..68270f2 --- /dev/null +++ b/.github/workflows/cachebusting.yml @@ -0,0 +1,26 @@ +name: Cache Busting +on: + push: + branches: + - "main" + - "testing" + pull_request: + branches: [main, testing] + types: [opened, synchronize, closed] + +jobs: + update_hashes: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.ref }} + - name: Update hashes in html files + run: bash .devtools/updatehashes.sh + - name: Commit + uses: EndBug/add-and-commit@v9.1.1 + with: + committer_name: Github Actions + committer_email: actions@github.com + message: "Fixed resource hashes" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2998c38..57be695 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,9 +17,10 @@ We use github to host code, to track issues and feature requests, as well as acc 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: 1. Fork the repo and create your branch from `main` or `testing`. -2. 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. -3. 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`. -4. Create a pull request with a short description of what you did. Thanks for your contribution! +2. Setup [commit hooks](../openOutpaint/.devtools/README.md) for automatic calculation of cache busting hashes for resources. +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. +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`. +5. Create a pull request with a short description of what you did. Thanks for your contribution! ## Any contributions you make will be under the MIT Software License diff --git a/index.html b/index.html index 34dce50..faf2671 100644 --- a/index.html +++ b/index.html @@ -4,22 +4,22 @@ openOutpaint 🐠 - - + + - - + + - + - - - + + + - - - + + + @@ -100,6 +100,12 @@
+ + +
- + - - - - - + + + + + - - + + - + - - + + - - + + - + - - - - - - + + + + + + + - - + diff --git a/js/global.js b/js/global.js index 2c60124..19a3542 100644 --- a/js/global.js +++ b/js/global.js @@ -20,6 +20,9 @@ const global = { // If there is a selected input hasActiveInput: false, + // If cursor size sync is enabled + syncCursorSize: false, + // If debugging is enabled _debug: false, set debug(v) { diff --git a/js/index.js b/js/index.js index 8c9505d..133439f 100644 --- a/js/index.js +++ b/js/index.js @@ -105,6 +105,7 @@ var stableDiffusionData = { inpaint_full_res: false, inpainting_fill: 2, enable_hr: false, + restore_faces: false, firstphase_width: 0, firstphase_height: 0, styles: [], @@ -158,6 +159,7 @@ function startup() { changeSmoothRendering(); changeSeed(); changeHiResFix(); + changeRestoreFaces(); changeSyncCursorSize(); } @@ -553,7 +555,10 @@ const resSlider = makeSlider( stableDiffusionData.width = stableDiffusionData.height = v; stableDiffusionData.firstphase_width = stableDiffusionData.firstphase_height = v / 2; - informCursorSizeSlider(); + + toolbar.currentTool && + toolbar.currentTool.redraw && + toolbar.currentTool.redraw(); } ); makeSlider( @@ -616,17 +621,21 @@ function changeHiResFix() { localStorage.setItem("openoutpaint/enable_hr", stableDiffusionData.enable_hr); } -function changeSyncCursorSize() { - stableDiffusionData.sync_cursor_size = Boolean( - document.getElementById("cbxSyncCursorSize").checked - ); //is this horribly hacky, putting it in SD data instead of making a gross global var? - localStorage.setItem( - "openoutpaint/sync_cursor_size", - stableDiffusionData.sync_cursor_size +function changeRestoreFaces() { + stableDiffusionData.restore_faces = Boolean( + document.getElementById("cbxRestoreFaces").checked ); - if (stableDiffusionData.sync_cursor_size) { - resSlider.value = stableDiffusionData.width; - } + localStorage.setItem( + "openoutpaint/restore_faces", + stableDiffusionData.restore_faces + ); +} + +function changeSyncCursorSize() { + global.syncCursorSize = Boolean( + document.getElementById("cbxSyncCursorSize").checked + ); + localStorage.setItem("openoutpaint/sync_cursor_size", global.syncCursorSize); } function changeSmoothRendering() { @@ -1007,6 +1016,10 @@ function loadSettings() { localStorage.getItem("openoutpaint/enable_hr") === null ? false : localStorage.getItem("openoutpaint/enable_hr") === "true"; + let _restore_faces = + localStorage.getItem("openoutpaint/restore_faces") === null + ? false + : localStorage.getItem("openoutpaint/restore_faces") === "true"; let _sync_cursor_size = localStorage.getItem("openoutpaint/sync_cursor_size") === null @@ -1017,6 +1030,7 @@ function loadSettings() { document.getElementById("maskBlur").value = Number(_mask_blur); document.getElementById("seed").value = Number(_seed); document.getElementById("cbxHRFix").checked = Boolean(_enable_hr); + document.getElementById("cbxRestoreFaces").checked = Boolean(_restore_faces); document.getElementById("cbxSyncCursorSize").checked = Boolean(_sync_cursor_size); } @@ -1025,9 +1039,6 @@ imageCollection.element.addEventListener( "wheel", (evn) => { evn.preventDefault(); - if (!evn.ctrlKey) { - _resolution_onwheel(evn); - } }, {passive: false} ); @@ -1045,25 +1056,3 @@ function resetToDefaults() { localStorage.clear(); } } - -function informCursorSizeSlider() { - if (stableDiffusionData.sync_cursor_size) { - if (toolbar._current_tool) { - if (!toolbar._current_tool.state.ignorePrevious) { - toolbar._current_tool.state.setCursorSize(stableDiffusionData.width); - } - toolbar._current_tool.state.ignorePrevious = false; - } - } -} - -const _resolution_onwheel = (evn) => { - if ( - stableDiffusionData.sync_cursor_size && - !toolbar._current_tool.state.block_res_change - ) { - toolbar._current_tool.state.ignorePrevious = true; //so hacky - resSlider.value = - stableDiffusionData.width - (128 * evn.deltaY) / Math.abs(evn.deltaY); - } -}; diff --git a/js/lib/toolbar.js b/js/lib/toolbar.js index 670dfd6..d8cad9b 100644 --- a/js/lib/toolbar.js +++ b/js/lib/toolbar.js @@ -181,6 +181,7 @@ const _toolbar_input = { return { slider, + rawSlider: value, setValue(v) { value.value = v; return value.value; diff --git a/js/lib/ui.js b/js/lib/ui.js index 28c1b1d..5e4cd22 100644 --- a/js/lib/ui.js +++ b/js/lib/ui.js @@ -74,7 +74,7 @@ function makeDraggable(element) { * @param {number} option.defaultValue The default value of the slider * @param {number} [options.textStep=step] The step size for the slider text and setvalue \ * (usually finer, and an integer divisor of step size) - * @returns {{value: number}} A reference to the value of the slider + * @returns {{value: number, onchange: Observer<{value: number}>}} A reference to the value of the slider */ function createSlider(name, wrapper, options = {}) { defaultOpt(options, { @@ -124,6 +124,10 @@ function createSlider(name, wrapper, options = {}) { underEl.appendChild(bar); underEl.appendChild(document.createElement("div")); + // Change observer + /** @type {Observer<{value: number}>} */ + const onchange = new Observer(); + // Set value const setValue = (val) => { phantomTextRange.value = val; @@ -133,6 +137,7 @@ function createSlider(name, wrapper, options = {}) { }%`; textEl.value = `${name}: ${value}`; options.valuecb && options.valuecb(value); + onchange.emit({value: val}); }; setValue(options.defaultValue); @@ -184,6 +189,7 @@ function createSlider(name, wrapper, options = {}) { }); return { + onchange, set value(val) { setValue(val); }, diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js index ada341f..adb6224 100644 --- a/js/ui/tool/dream.js +++ b/js/ui/tool/dream.js @@ -1391,14 +1391,24 @@ const dreamTool = () => step: 128, textStep: 2, cb: () => { - if (stableDiffusionData.sync_cursor_size) { - state.ignorePrevious = true; + if ( + global.syncCursorSize && + resSlider.value !== state.cursorSize + ) { resSlider.value = state.cursorSize; } + + state.redraw(); }, } ); + resSlider.onchange.on(({value}) => { + if (global.syncCursorSize && value !== state.cursorSize) { + cursorSizeSlider.rawSlider.value = value; + } + }); + state.setCursorSize = cursorSizeSlider.setValue; state.ctxmenu.cursorSizeSlider = cursorSizeSlider.slider; @@ -1876,14 +1886,19 @@ const img2imgTool = () => step: 128, textStep: 2, cb: () => { - if (stableDiffusionData.sync_cursor_size) { - state.ignorePrevious = true; + if (global.syncCursorSize) { resSlider.value = state.cursorSize; } }, } ); + resSlider.onchange.on(({value}) => { + if (global.syncCursorSize && value !== state.cursorSize) { + cursorSizeSlider.rawSlider.value = value; + } + }); + state.setCursorSize = cursorSizeSlider.setValue; state.ctxmenu.cursorSizeSlider = cursorSizeSlider.slider; diff --git a/pages/configuration.html b/pages/configuration.html index 42483db..313a527 100644 --- a/pages/configuration.html +++ b/pages/configuration.html @@ -4,22 +4,22 @@ openOutpaint 🐠 - - + + - - + + - + - - - + + + - - - + + +