diff --git a/css/icons.css b/css/icons.css
index a3b8ca9..e808b3b 100644
--- a/css/icons.css
+++ b/css/icons.css
@@ -1,3 +1,34 @@
+.ui.inline-icon {
+ position: relative;
+
+ display: flex;
+}
+
+.ui.inline-icon::after {
+ content: "";
+ display: block;
+
+ position: absolute;
+
+ box-sizing: border-box;
+
+ margin: auto;
+ top: 15%;
+ bottom: 15%;
+
+ mask-size: contain;
+ mask-repeat: no-repeat;
+
+ max-height: 70%;
+ aspect-ratio: 1;
+
+ left: 0;
+ right: 0;
+
+ background-color: var(--c-text);
+}
+
+.ui.inline-icon.icon-eye-off::after,
.ui.icon > .icon-eye-off {
-webkit-mask-image: url("../res/icons/eye-off.svg");
mask-image: url("../res/icons/eye-off.svg");
@@ -42,3 +73,57 @@
-webkit-mask-image: url("../res/icons/settings.svg");
mask-image: url("../res/icons/settings.svg");
}
+
+.ui.inline-icon.icon-grid::after,
+.ui.icon > .icon-grid {
+ -webkit-mask-image: url("../res/icons/grid.svg");
+ mask-image: url("../res/icons/grid.svg");
+}
+
+.ui.inline-icon.icon-venetian-mask::after,
+.ui.icon > .icon-venetian-mask {
+ -webkit-mask-image: url("../res/icons/venetian-mask.svg");
+ mask-image: url("../res/icons/venetian-mask.svg");
+}
+
+.ui.inline-icon.icon-brush::after,
+.ui.icon > .icon-brush {
+ -webkit-mask-image: url("../res/icons/brush.svg");
+ mask-image: url("../res/icons/brush.svg");
+}
+
+.ui.inline-icon.icon-paintbrush::after,
+.ui.icon > .icon-paintbrush {
+ -webkit-mask-image: url("../res/icons/paintbrush.svg");
+ mask-image: url("../res/icons/paintbrush.svg");
+}
+
+.ui.inline-icon.icon-expand::after,
+.ui.icon > .icon-expand {
+ -webkit-mask-image: url("../res/icons/expand.svg");
+ mask-image: url("../res/icons/expand.svg");
+}
+
+.ui.inline-icon.icon-pin::after,
+.ui.icon > .icon-pin {
+ -webkit-mask-image: url("../res/icons/pin.svg");
+ mask-image: url("../res/icons/pin.svg");
+}
+
+.ui.inline-icon.icon-box-select::after,
+.ui.icon > .icon-box-select {
+ -webkit-mask-image: url("../res/icons/box-select.svg");
+ mask-image: url("../res/icons/box-select.svg");
+}
+
+.ui.inline-icon.icon-maximize::after,
+.ui.icon > .icon-maximize {
+ -webkit-mask-image: url("../res/icons/maximize.svg");
+ mask-image: url("../res/icons/maximize.svg");
+}
+
+.ui.inline-icon.icon-clipboard-list::after,
+.ui.icon > .icon-clipboard-list {
+ -webkit-mask-image: url("../res/icons/clipboard-list.svg");
+ mask-image: url("../res/icons/clipboard-list.svg");
+}
diff --git a/css/ui/generic.css b/css/ui/generic.css
index 93caf35..801e2ba 100644
--- a/css/ui/generic.css
+++ b/css/ui/generic.css
@@ -37,6 +37,8 @@
/* Slider Input */
div.slider-wrapper {
margin: 5px;
+ margin-left: 0;
+ margin-right: 0;
}
div.slider-wrapper {
@@ -100,6 +102,83 @@ div.slider-wrapper > input.text {
background-color: transparent;
}
+/* Checkbox Input */
+div.checkbox-array {
+ display: flex;
+
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
+
+input.oo-checkbox[type="checkbox"] {
+ /* Hide original checkbox */
+ -webkit-appearance: none;
+ appearance: none;
+
+ flex: 1;
+
+ margin: 0;
+
+ min-width: 28px;
+ height: 28px;
+
+ background-color: var(--c-primary);
+
+ cursor: pointer;
+}
+
+input.oo-checkbox[type="checkbox"]:disabled {
+ background-color: #666 !important;
+ cursor: default !important;
+}
+
+input.oo-checkbox[type="checkbox"]:disabled:hover {
+ filter: none !important;
+}
+
+input.oo-checkbox[type="checkbox"]:checked::after {
+ background-color: #66f;
+}
+
+input.oo-checkbox[type="checkbox"]:hover {
+ background-color: var(--c-hover);
+}
+
+input.oo-checkbox[type="checkbox"]:active {
+ filter: brightness(120%);
+}
+
+input.oo-checkbox[type="checkbox"]:first-child {
+ border-top-left-radius: 5px;
+ border-bottom-left-radius: 5px;
+}
+
+input.oo-checkbox[type="checkbox"]:last-child {
+ border-top-right-radius: 5px;
+ border-bottom-right-radius: 5px;
+}
+
+/* Mask Inversion Checkbox */
+input.oo-checkbox[type="checkbox"].invert-mask-checkbox::after {
+ background-color: var(--c-text);
+}
+
+input.oo-checkbox[type="checkbox"].invert-mask-checkbox:hover {
+ filter: brightness(120%);
+}
+
+input.oo-checkbox[type="checkbox"].invert-mask-checkbox:active {
+ filter: brightness(140%);
+}
+
+input.oo-checkbox[type="checkbox"].invert-mask-checkbox {
+ background-color: #922;
+}
+
+input.oo-checkbox[type="checkbox"].invert-mask-checkbox:checked {
+ background-color: #229;
+}
+
/* Bare Select */
.bareselector {
diff --git a/index.html b/index.html
index 25a4e67..6bd3985 100644
--- a/index.html
+++ b/index.html
@@ -5,12 +5,12 @@
openOutpaint 🐠
-
+
-
+
@@ -98,9 +98,12 @@
step="1" />
-
+
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
@@ -187,7 +190,7 @@
- Alpha release v0.0.12.3
+ Alpha release v0.0.12.5
@@ -311,12 +314,12 @@
+ src="pages/configuration.html?v=3d710ce">
-
+
@@ -325,7 +328,7 @@
-
+
-
+
-
+
diff --git a/js/global.js b/js/global.js
index 19a3542..72cb565 100644
--- a/js/global.js
+++ b/js/global.js
@@ -3,6 +3,11 @@
*/
const global = {
+ // If this is the first run of openOutpaint
+ get firstRun() {
+ return this._firstRun;
+ },
+
// Connection
_connection: "offline",
set connection(v) {
@@ -46,3 +51,5 @@ const global = {
this.debug = !this.debug;
},
};
+
+global._firstRun = !localStorage.getItem("openoutpaint/host");
diff --git a/js/index.js b/js/index.js
index fb68673..dabd70e 100644
--- a/js/index.js
+++ b/js/index.js
@@ -103,11 +103,13 @@ var stableDiffusionData = {
mask: "",
init_images: [],
inpaint_full_res: false,
- inpainting_fill: 2,
+ inpainting_fill: 1,
enable_hr: false,
restore_faces: false,
- firstphase_width: 0,
- firstphase_height: 0,
+ //firstphase_width: 0,
+ //firstphase_height: 0, //20230102 welp looks like the entire way HRfix is implemented has become bonkersly different
+ hr_scale: 2.0,
+ hr_upscaler: "None",
styles: [],
// here's some more fields that might be useful
@@ -137,7 +139,6 @@ var host = "";
var url = "/sdapi/v1/";
const basePixelCount = 64; //64 px - ALWAYS 64 PX
-//
function startup() {
testHostConfiguration();
loadSettings();
@@ -341,6 +342,12 @@ async function testHostConnection() {
const response = await fetch(
document.getElementById("host").value + "/sdapi/v1/options"
);
+ const optionsdata = await response.json();
+ if (optionsdata["use_scale_latent_for_hires_fix"]) {
+ const message = `You are using an outdated version of A1111 webUI.\nThe HRfix options will not work until you update to at least commit ef27a18\n(https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/ef27a18b6b7cb1a8eebdc9b2e88d25baf2c2414d)\nor newer.`;
+ console.error(message);
+ alert(message);
+ }
switch (response.status) {
case 200: {
setConnectionStatus("online");
@@ -552,6 +559,15 @@ const upscalerAutoComplete = createAutoComplete(
document.getElementById("upscaler-ac-select")
);
+const hrFixUpscalerAutoComplete = createAutoComplete(
+ "HRfix Upscaler",
+ document.getElementById("hrFixUpscaler")
+);
+hrFixUpscalerAutoComplete.onchange.on(({value}) => {
+ stableDiffusionData.hr_upscaler = value;
+ localStorage.setItem(`openoutpaint/hr_upscaler`, value);
+});
+
const resSlider = makeSlider(
"Resolution",
document.getElementById("resolution"),
@@ -563,8 +579,6 @@ const resSlider = makeSlider(
2,
(v) => {
stableDiffusionData.width = stableDiffusionData.height = v;
- stableDiffusionData.firstphase_width =
- stableDiffusionData.firstphase_height = v / 2;
toolbar.currentTool &&
toolbar.currentTool.redraw &&
@@ -621,15 +635,27 @@ makeSlider(
1
);
+// 20230102 grumble grumble
makeSlider(
- "HRfix Lock Px.",
- document.getElementById("hrFixLock"),
- "hr_fix_lock_px",
+ "HRfix Scale",
+ document.getElementById("hrFixScale"),
+ "hr_scale",
+ 1.0,
+ 4.0,
+ 0.1,
+ 2.0,
+ 0.1
+);
+
+makeSlider(
+ "HRfix Denoising",
+ document.getElementById("hrDenoising"),
+ "hr_denoising_strength",
0.0,
- 768.0,
- 256.0,
- 0.0,
- 1.0
+ 1.0,
+ 0.05,
+ 0.7,
+ 0.01
);
function changeMaskBlur() {
@@ -649,6 +675,23 @@ function changeHiResFix() {
document.getElementById("cbxHRFix").checked
);
localStorage.setItem("openoutpaint/enable_hr", stableDiffusionData.enable_hr);
+ var hrfSlider = document.getElementById("hrFixScale");
+ var hrfOpotions = document.getElementById("hrFixUpscaler");
+ var hrfLabel = document.getElementById("hrFixLabel");
+ var hrfDenoiseSlider = document.getElementById("hrDenoising");
+ if (stableDiffusionData.enable_hr) {
+ hrfSlider.classList.remove("invisible");
+ hrfOpotions.classList.remove("invisible");
+ hrfLabel.classList.remove("invisible");
+ hrfDenoiseSlider.classList.remove("invisible");
+ //state.ctxmenu.keepUnmaskedBlurSliderLinebreak.classList.add("invisible");
+ } else {
+ hrfSlider.classList.add("invisible");
+ hrfOpotions.classList.add("invisible");
+ hrfLabel.classList.add("invisible");
+ hrfDenoiseSlider.classList.add("invisible");
+ //state.ctxmenu.keepUnmaskedBlurSliderLinebreak.classList.remove("invisible");
+ }
}
function changeRestoreFaces() {
@@ -743,17 +786,26 @@ async function getUpscalers() {
"[index] purposefully_incorrect_data response, ignore above error"
);
// result = purposefully_incorrect_data response: Invalid upscaler, needs to be on of these: None , Lanczos , Nearest , LDSR , BSRGAN , R-ESRGAN General 4xV3 , R-ESRGAN 4x+ Anime6B , ScuNET , ScuNET PSNR , SwinIR_4x
- const upscalers = data.detail
+ const upscalersPlusNone = data.detail
.split(": ")[1]
.split(",")
- .map((v) => v.trim())
- .filter((v) => v !== "None"); // converting the result to a list of upscalers
+ .map((v) => v.trim()); // need "None" for stupid hrfix changes razza frazza
+ const upscalers = upscalersPlusNone.filter((v) => v !== "None"); // converting the result to a list of upscalers
+ upscalersPlusNone.push("Latent");
+ upscalersPlusNone.push("Latent (nearest)"); // GRUMBLE GRUMBLE
upscalerAutoComplete.options = upscalers.map((u) => {
return {name: u, value: u};
});
+ hrFixUpscalerAutoComplete.options = upscalersPlusNone.map((u) => {
+ return {name: u, value: u};
+ });
upscalerAutoComplete.value = upscalers[0];
+ hrFixUpscalerAutoComplete.value =
+ localStorage.getItem("openoutpaint/hr_upscaler") === null
+ ? "None"
+ : localStorage.getItem("openoutpaint/hr_upscaler");
} catch (e) {
console.warn("[index] Failed to fetch upscalers:");
console.warn(e);
@@ -804,12 +856,14 @@ async function getUpscalers() {
}
async function getModels() {
- var url = document.getElementById("host").value + "/sdapi/v1/sd-models";
+ const url = document.getElementById("host").value + "/sdapi/v1/sd-models";
+ let opt = null;
+
try {
const response = await fetch(url);
const data = await response.json();
- modelAutoComplete.options = data.map((option) => ({
+ opt = data.map((option) => ({
name: option.title,
value: option.title,
optionelcb: (el) => {
@@ -818,6 +872,8 @@ async function getModels() {
},
}));
+ modelAutoComplete.options = opt;
+
try {
const optResponse = await fetch(
document.getElementById("host").value + "/sdapi/v1/options"
@@ -838,10 +894,10 @@ async function getModels() {
modelAutoComplete.onchange.on(async ({value}) => {
console.log(`[index] Changing model to [${value}]`);
- var payload = {
+ const payload = {
sd_model_checkpoint: value,
};
- var url = document.getElementById("host").value + "/sdapi/v1/options/";
+ const url = document.getElementById("host").value + "/sdapi/v1/options/";
try {
await fetch(url, {
method: "POST",
@@ -861,6 +917,25 @@ async function getModels() {
);
}
});
+
+ // If first time running, ask if user wants to switch to an inpainting model
+ if (global.firstRun && !modelAutoComplete.value.includes("inpainting")) {
+ const inpainting = opt.find(({name}) => name.includes("inpainting"));
+
+ let message =
+ "It seems this is your first time using openOutpaint. It is highly recommended that you switch to an inpainting model. \
+ These are highlighted as green in the model selector.";
+
+ if (inpainting) {
+ message += `\n\nWe have found the inpainting model\n\n - ${inpainting.name}\n\navailable in the webui. Do you want to switch to it?`;
+ if (confirm(message)) {
+ modelAutoComplete.value = inpainting.value;
+ }
+ } else {
+ message += `\n\nNo 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.`;
+ alert(message);
+ }
+ }
}
async function getConfig() {
@@ -1060,6 +1135,15 @@ function loadSettings() {
? true
: localStorage.getItem("openoutpaint/sync_cursor_size") === "true";
+ let _hrfix_scale =
+ localStorage.getItem("openoutpaint/hr_scale") === null
+ ? 2.0
+ : localStorage.getItem("openoutpaint/hr_scale");
+
+ let _hrfix_denoising =
+ localStorage.getItem("openoutpaint/hr_denoising_strength") === null
+ ? 0.7
+ : localStorage.getItem("openoutpaint/hr_denoising_strength");
// set the values into the UI
document.getElementById("maskBlur").value = Number(_mask_blur);
document.getElementById("seed").value = Number(_seed);
@@ -1067,6 +1151,8 @@ function loadSettings() {
document.getElementById("cbxRestoreFaces").checked = Boolean(_restore_faces);
document.getElementById("cbxSyncCursorSize").checked =
Boolean(_sync_cursor_size);
+ document.getElementById("hrFixScale").value = Number(_hrfix_scale);
+ document.getElementById("hrDenoising").value = Number(_hrfix_denoising);
}
imageCollection.element.addEventListener(
diff --git a/js/lib/toolbar.js b/js/lib/toolbar.js
index 232b0fe..10e48f8 100644
--- a/js/lib/toolbar.js
+++ b/js/lib/toolbar.js
@@ -145,17 +145,24 @@ const toolbar = {
* Premade inputs for populating the context menus
*/
const _toolbar_input = {
- checkbox: (state, dataKey, text, cb = null) => {
+ checkbox: (state, dataKey, text, classes, cb = null) => {
if (state[dataKey] === undefined) state[dataKey] = false;
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
+ checkbox.classList.add("oo-checkbox", "ui", "inline-icon");
+
+ if (typeof classes === "string") classes = [classes];
+
+ if (classes) checkbox.classList.add(...classes);
checkbox.checked = state[dataKey];
checkbox.onchange = () => {
state[dataKey] = checkbox.checked;
cb && cb();
};
+ checkbox.title = text;
+
const label = document.createElement("label");
label.appendChild(checkbox);
label.appendChild(new Text(text));
diff --git a/js/ui/tool/colorbrush.js b/js/ui/tool/colorbrush.js
index 5786307..dc1d190 100644
--- a/js/ui/tool/colorbrush.js
+++ b/js/ui/tool/colorbrush.js
@@ -349,13 +349,16 @@ const colorBrushTool = () =>
state.ctxmenu = {};
// Affects Mask Checkbox
+ const array = document.createElement("div");
const affectMaskCheckbox = _toolbar_input.checkbox(
state,
"affectMask",
- "Affect Mask"
- ).label;
+ "Affect Mask",
+ "icon-venetian-mask"
+ ).checkbox;
+ array.appendChild(affectMaskCheckbox);
- state.ctxmenu.affectMaskCheckbox = affectMaskCheckbox;
+ state.ctxmenu.affectMaskCheckbox = array;
// Brush size slider
const brushSizeSlider = _toolbar_input.slider(
diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js
index 30e73fd..8d04257 100644
--- a/js/ui/tool/dream.js
+++ b/js/ui/tool/dream.js
@@ -130,6 +130,25 @@ const _dream = async (endpoint, request) => {
let data = null;
try {
generating = true;
+ if (
+ endpoint == "txt2img" &&
+ request.enable_hr &&
+ localStorage.getItem("openoutpaint/settings.hrfix-liar") == "true"
+ ) {
+ /**
+ * try and make the new HRfix method useful for our purposes
+ * since it now returns an image that's been upscaled x the hr_scale parameter,
+ * we cheekily lie to SD and tell it that the original dimensions are _divided_
+ * by the scale factor so it returns something about the same size as we wanted initially
+ */
+ var newWidth = Math.floor(request.width / request.hr_scale);
+ var newHeight = Math.floor(request.height / request.hr_scale);
+ request.width = newWidth;
+ request.height = newHeight;
+ }
+ if (endpoint == "txt2img") {
+ request.denoising_strength = stableDiffusionData.hr_denoising_strength;
+ }
const response = await fetch(apiURL, {
method: "POST",
headers: {
@@ -977,7 +996,7 @@ const dream_img2img_callback = (bb, resolution, state) => {
request.height = resolution.h;
request.denoising_strength = state.denoisingStrength;
- request.inpainting_fill = state.inpainting_fill; //let's see how this works //1; // For img2img use original
+ request.inpainting_fill = state.inpainting_fill ?? 1; //let's see how this works //1; // For img2img use original
// Load prompt (maybe we should add some events so we don't have to do this)
request.prompt = document.getElementById("prompt").value;
@@ -1392,18 +1411,6 @@ const dreamTool = () =>
h: stableDiffusionData.height,
};
- //hacky set non-square auto hrfix values
- let hrLockPx =
- localStorage.getItem("openoutpaint/hr_fix_lock_px") ?? 0;
- stableDiffusionData.firstphase_height =
- hrLockPx == 0 || resolution.h / 2 <= hrLockPx
- ? resolution.h / 2
- : hrLockPx;
- stableDiffusionData.firstphase_width =
- hrLockPx == 0 || resolution.w / 2 <= hrLockPx
- ? resolution.w / 2
- : hrLockPx;
-
if (global.connection === "online") {
dream_generate_callback(bb, resolution, state);
} else {
@@ -1474,34 +1481,43 @@ const dreamTool = () =>
state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox(
state,
"snapToGrid",
- "Snap To Grid"
- ).label;
+ "Snap To Grid",
+ "icon-grid"
+ ).checkbox;
// Invert Mask Checkbox
state.ctxmenu.invertMaskLabel = _toolbar_input.checkbox(
state,
"invertMask",
"Invert Mask",
+ ["icon-venetian-mask", "invert-mask-checkbox"],
() => {
setMask(state.invertMask ? "hold" : "clear");
}
- ).label;
+ ).checkbox;
// Keep Masked Content Checkbox
state.ctxmenu.keepUnmaskedLabel = _toolbar_input.checkbox(
state,
"keepUnmasked",
"Keep Unmasked",
+ "icon-pin",
() => {
if (state.keepUnmasked) {
state.ctxmenu.keepUnmaskedBlurSlider.classList.remove(
"invisible"
);
+ state.ctxmenu.keepUnmaskedBlurSliderLinebreak.classList.add(
+ "invisible"
+ );
} else {
state.ctxmenu.keepUnmaskedBlurSlider.classList.add("invisible");
+ state.ctxmenu.keepUnmaskedBlurSliderLinebreak.classList.remove(
+ "invisible"
+ );
}
}
- ).label;
+ ).checkbox;
// Keep Masked Content Blur Slider
state.ctxmenu.keepUnmaskedBlurSlider = _toolbar_input.slider(
@@ -1516,12 +1532,19 @@ const dreamTool = () =>
}
).slider;
+ state.ctxmenu.keepUnmaskedBlurSliderLinebreak =
+ document.createElement("br");
+ state.ctxmenu.keepUnmaskedBlurSliderLinebreak.classList.add(
+ "invisible"
+ );
+
// Preserve Brushed Masks Checkbox
state.ctxmenu.preserveMasksLabel = _toolbar_input.checkbox(
state,
"preserveMasks",
- "Preserve Brushed Masks"
- ).label;
+ "Preserve Brushed Masks",
+ "icon-paintbrush"
+ ).checkbox;
// Overmasking Slider
state.ctxmenu.overMaskPxLabel = _toolbar_input.slider(
@@ -1551,14 +1574,19 @@ const dreamTool = () =>
}
menu.appendChild(state.ctxmenu.cursorSizeSlider);
- menu.appendChild(state.ctxmenu.snapToGridLabel);
- menu.appendChild(document.createElement("br"));
- menu.appendChild(state.ctxmenu.invertMaskLabel);
- menu.appendChild(document.createElement("br"));
- menu.appendChild(state.ctxmenu.keepUnmaskedLabel);
+ const array = document.createElement("div");
+ array.classList.add("checkbox-array");
+ array.appendChild(state.ctxmenu.snapToGridLabel);
+ //menu.appendChild(document.createElement("br"));
+ array.appendChild(state.ctxmenu.invertMaskLabel);
+ array.appendChild(state.ctxmenu.preserveMasksLabel);
+ //menu.appendChild(document.createElement("br"));
+ array.appendChild(state.ctxmenu.keepUnmaskedLabel);
+ menu.appendChild(array);
menu.appendChild(state.ctxmenu.keepUnmaskedBlurSlider);
- menu.appendChild(state.ctxmenu.preserveMasksLabel);
- menu.appendChild(document.createElement("br"));
+ // menu.appendChild(state.ctxmenu.keepUnmaskedBlurSliderLinebreak);
+ // menu.appendChild(state.ctxmenu.preserveMasksLabel);
+ // menu.appendChild(document.createElement("br"));
menu.appendChild(state.ctxmenu.overMaskPxLabel);
menu.appendChild(state.ctxmenu.eagerGenerateCountLabel);
},
@@ -1979,24 +2007,27 @@ const img2imgTool = () =>
state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox(
state,
"snapToGrid",
- "Snap To Grid"
- ).label;
+ "Snap To Grid",
+ "icon-grid"
+ ).checkbox;
// Invert Mask Checkbox
state.ctxmenu.invertMaskLabel = _toolbar_input.checkbox(
state,
"invertMask",
"Invert Mask",
+ ["icon-venetian-mask", "invert-mask-checkbox"],
() => {
setMask(state.invertMask ? "hold" : "clear");
}
- ).label;
+ ).checkbox;
// Keep Masked Content Checkbox
state.ctxmenu.keepUnmaskedLabel = _toolbar_input.checkbox(
state,
"keepUnmasked",
"Keep Unmasked",
+ "icon-pin",
() => {
if (state.keepUnmasked) {
state.ctxmenu.keepUnmaskedBlurSlider.classList.remove(
@@ -2012,7 +2043,7 @@ const img2imgTool = () =>
);
}
}
- ).label;
+ ).checkbox;
// Keep Masked Content Blur Slider
state.ctxmenu.keepUnmaskedBlurSlider = _toolbar_input.slider(
@@ -2037,15 +2068,17 @@ const img2imgTool = () =>
state.ctxmenu.preserveMasksLabel = _toolbar_input.checkbox(
state,
"preserveMasks",
- "Preserve Brushed Masks"
- ).label;
+ "Preserve Brushed Masks",
+ "icon-paintbrush"
+ ).checkbox;
// Inpaint Full Resolution Checkbox
state.ctxmenu.fullResolutionLabel = _toolbar_input.checkbox(
state,
"fullResolution",
- "Inpaint Full Resolution"
- ).label;
+ "Inpaint Full Resolution",
+ "icon-expand"
+ ).checkbox;
// Denoising Strength Slider
state.ctxmenu.denoisingStrengthSlider = _toolbar_input.slider(
@@ -2064,8 +2097,9 @@ const img2imgTool = () =>
state.ctxmenu.borderMaskGradientCheckbox = _toolbar_input.checkbox(
state,
"gradient",
- "Border Mask Gradient"
- ).label;
+ "Border Mask Gradient",
+ "icon-box-select"
+ ).checkbox;
// Border Mask Size Slider
state.ctxmenu.borderMaskSlider = _toolbar_input.slider(
@@ -2112,20 +2146,22 @@ const img2imgTool = () =>
}
menu.appendChild(state.ctxmenu.cursorSizeSlider);
- menu.appendChild(state.ctxmenu.snapToGridLabel);
- menu.appendChild(document.createElement("br"));
- menu.appendChild(state.ctxmenu.invertMaskLabel);
- menu.appendChild(document.createElement("br"));
- menu.appendChild(state.ctxmenu.keepUnmaskedLabel);
+ const array = document.createElement("div");
+ array.classList.add("checkbox-array");
+ array.appendChild(state.ctxmenu.snapToGridLabel);
+ array.appendChild(state.ctxmenu.invertMaskLabel);
+ array.appendChild(state.ctxmenu.preserveMasksLabel);
+ array.appendChild(state.ctxmenu.keepUnmaskedLabel);
+ menu.appendChild(array);
menu.appendChild(state.ctxmenu.keepUnmaskedBlurSlider);
- menu.appendChild(state.ctxmenu.keepUnmaskedBlurSliderLinebreak);
- menu.appendChild(state.ctxmenu.preserveMasksLabel);
- menu.appendChild(document.createElement("br"));
- menu.appendChild(state.ctxmenu.fullResolutionLabel);
- menu.appendChild(document.createElement("br"));
+ // menu.appendChild(state.ctxmenu.keepUnmaskedBlurSliderLinebreak);
menu.appendChild(state.ctxmenu.inpaintTypeSelect);
menu.appendChild(state.ctxmenu.denoisingStrengthSlider);
- menu.appendChild(state.ctxmenu.borderMaskGradientCheckbox);
+ const btnArray2 = document.createElement("div");
+ btnArray2.classList.add("checkbox-array");
+ btnArray2.appendChild(state.ctxmenu.fullResolutionLabel);
+ btnArray2.appendChild(state.ctxmenu.borderMaskGradientCheckbox);
+ menu.appendChild(btnArray2);
menu.appendChild(state.ctxmenu.borderMaskSlider);
menu.appendChild(state.ctxmenu.eagerGenerateCountLabel);
},
diff --git a/js/ui/tool/interrogate.js b/js/ui/tool/interrogate.js
index 2090c03..b7fc403 100644
--- a/js/ui/tool/interrogate.js
+++ b/js/ui/tool/interrogate.js
@@ -97,8 +97,9 @@ const interrogateTool = () =>
state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox(
state,
"snapToGrid",
- "Snap To Grid"
- ).label;
+ "Snap To Grid",
+ "icon-grid"
+ ).checkbox;
}
menu.appendChild(state.ctxmenu.cursorSizeSlider);
diff --git a/js/ui/tool/select.js b/js/ui/tool/select.js
index c62cf14..11eb700 100644
--- a/js/ui/tool/select.js
+++ b/js/ui/tool/select.js
@@ -633,23 +633,26 @@ const selectTransformTool = () =>
state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox(
state,
"snapToGrid",
- "Snap To Grid"
- ).label;
+ "Snap To Grid",
+ "icon-grid"
+ ).checkbox;
// Keep Aspect Ratio
state.ctxmenu.keepAspectRatioLabel = _toolbar_input.checkbox(
state,
"keepAspectRatio",
- "Keep Aspect Ratio"
- ).label;
+ "Keep Aspect Ratio",
+ "icon-maximize"
+ ).checkbox;
// Use Clipboard
const clipboardCheckbox = _toolbar_input.checkbox(
state,
"useClipboard",
- "Use clipboard"
+ "Use clipboard",
+ "icon-clipboard-list"
);
- state.ctxmenu.useClipboardLabel = clipboardCheckbox.label;
+ state.ctxmenu.useClipboardLabel = clipboardCheckbox.checkbox;
if (!(navigator.clipboard && navigator.clipboard.write))
clipboardCheckbox.checkbox.disabled = true; // Disable if not available
@@ -760,11 +763,12 @@ const selectTransformTool = () =>
state.ctxmenu.actionArray = actionArray;
state.ctxmenu.visibleActionArray = visibleActionArray;
}
- menu.appendChild(state.ctxmenu.snapToGridLabel);
- menu.appendChild(document.createElement("br"));
- menu.appendChild(state.ctxmenu.keepAspectRatioLabel);
- menu.appendChild(document.createElement("br"));
- menu.appendChild(state.ctxmenu.useClipboardLabel);
+ const array = document.createElement("div");
+ array.classList.add("checkbox-array");
+ array.appendChild(state.ctxmenu.snapToGridLabel);
+ array.appendChild(state.ctxmenu.keepAspectRatioLabel);
+ array.appendChild(state.ctxmenu.useClipboardLabel);
+ menu.appendChild(array);
menu.appendChild(state.ctxmenu.selectionPeekOpacitySlider);
menu.appendChild(state.ctxmenu.actionArray);
menu.appendChild(state.ctxmenu.visibleActionArray);
diff --git a/js/ui/tool/stamp.js b/js/ui/tool/stamp.js
index 74be4ad..fc1cb89 100644
--- a/js/ui/tool/stamp.js
+++ b/js/ui/tool/stamp.js
@@ -368,11 +368,17 @@ const stampTool = () =>
if (!state.ctxmenu) {
state.ctxmenu = {};
// Snap To Grid Checkbox
- state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox(
- state,
- "snapToGrid",
- "Snap To Grid"
- ).label;
+ const array = document.createElement("div");
+ array.classList.add("checkbox-array");
+ array.appendChild(
+ _toolbar_input.checkbox(
+ state,
+ "snapToGrid",
+ "Snap To Grid",
+ "icon-grid"
+ ).checkbox
+ );
+ state.ctxmenu.snapToGridLabel = array;
// Create resource list
const uploadButtonId = `upload-btn-${guid()}`;
diff --git a/pages/configuration.html b/pages/configuration.html
index 2adff2a..5e53994 100644
--- a/pages/configuration.html
+++ b/pages/configuration.html
@@ -5,12 +5,12 @@
openOutpaint 🐠
-
+
-
+
@@ -84,6 +84,10 @@
step="0.1"
value="30.0" />
+
Refresh the page to apply settings.