Merge branch 'main' into win-hooks
This commit is contained in:
commit
ce80d9d10c
10 changed files with 254 additions and 19 deletions
|
@ -22,7 +22,7 @@ this is a completely vanilla javascript and html canvas outpainting convenience
|
|||
- queueable, cancelable dreams - just start a'clickin' all over the place
|
||||
- arbitrary dream reticle size - draw the rectangle of your dreams
|
||||
- an [effectively infinite](https://github.com/zero01101/openOutpaint/pull/108), resizable, scalable canvas for you to paint all over
|
||||
- **_NOTE: v0.0.10 introduces a new "camera control" modifier key - hold [`CTRL`] ([`CMD`] on mac) and use the scrollwheel to zoom (scroll the wheel) and pan (hold the wheel button) around the canvas_**
|
||||
- **_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_**
|
||||
- a very nicely functional and familiar layer system
|
||||
- inpainting/touchup mask brush
|
||||
- prompt history panel
|
||||
|
@ -36,12 +36,14 @@ this is a completely vanilla javascript and html canvas outpainting convenience
|
|||
- floating toolbox with handy keyboard shortcuts
|
||||
- optional grid snapping for precision
|
||||
- optional hi-res fix for blank/txt2img dreams which, if enabled, uses image width/height / 2 as firstpass size
|
||||
- optional HRfix lock px to constrain maximum firstpass values
|
||||
- optional overmasking for potentially better seams between outpaints - set overmask px value to 0 to disable the feature
|
||||
- import arbitrary images and scale/stamp on the canvas whenever, wherever you'd like
|
||||
- upscaler support for final output images
|
||||
- saves your preferences/imported images to browser localstorage for maximum convenience
|
||||
- reset to defaults button to unsave your preferences if things go squirrely
|
||||
- floating navigable undo/redo palette with ctrl+z/y keyboard shortcuts for additional maximum convenience and desquirreliness
|
||||
- optional generate-ahead function to keep crankin' out the dreams while you look through the ones that already exist
|
||||
- _all this and much more for the low, low price of simply already owning an expensive GPU!_
|
||||
|
||||
## operation
|
||||
|
|
|
@ -304,6 +304,15 @@ input#host {
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Model Select */
|
||||
#models-ac-select option {
|
||||
background-color: #fcc;
|
||||
}
|
||||
|
||||
#models-ac-select option.inpainting {
|
||||
background-color: #cfc;
|
||||
}
|
||||
|
||||
/* Settings button */
|
||||
.ui.icon.header-button {
|
||||
padding: 0;
|
||||
|
|
|
@ -100,6 +100,26 @@ div.slider-wrapper > input.text {
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* Bare Select */
|
||||
|
||||
.bareselector {
|
||||
border-radius: 5px;
|
||||
|
||||
background-color: white;
|
||||
|
||||
overflow-y: auto;
|
||||
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
|
||||
max-height: 200px;
|
||||
min-width: 100%;
|
||||
max-width: 800px;
|
||||
|
||||
width: fit-content;
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
/* Autocomplete Select */
|
||||
div.autocomplete {
|
||||
border-radius: 5px;
|
||||
|
|
17
index.html
17
index.html
|
@ -7,10 +7,10 @@
|
|||
<link href="css/colors.css?v=3f81e80" rel="stylesheet" />
|
||||
<link href="css/icons.css?v=a25504c" rel="stylesheet" />
|
||||
|
||||
<link href="css/index.css?v=ef0c943" rel="stylesheet" />
|
||||
<link href="css/index.css?v=69d3b9e" rel="stylesheet" />
|
||||
<link href="css/layers.css?v=b4fbf61" rel="stylesheet" />
|
||||
|
||||
<link href="css/ui/generic.css?v=a15ce4b" rel="stylesheet" />
|
||||
<link href="css/ui/generic.css?v=79bee9b" rel="stylesheet" />
|
||||
|
||||
<link href="css/ui/history.css?v=0b03861" rel="stylesheet" />
|
||||
<link href="css/ui/layers.css?v=4fd95fe" rel="stylesheet" />
|
||||
|
@ -100,6 +100,7 @@
|
|||
<input type="checkbox" id="cbxHRFix" onchange="changeHiResFix()" />
|
||||
<label for="cbxHRFix">Auto txt2img HRfix</label>
|
||||
<br />
|
||||
<div id="hrFixLock"></div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="cbxRestoreFaces"
|
||||
|
@ -186,7 +187,7 @@
|
|||
<br />
|
||||
<span id="version">
|
||||
<a href="https://github.com/zero01101/openOutpaint" target="_blank">
|
||||
Alpha release v0.0.12.1
|
||||
Alpha release v0.0.12.3
|
||||
</a>
|
||||
</span>
|
||||
<br />
|
||||
|
@ -310,7 +311,7 @@
|
|||
<div class="ui separator"></div>
|
||||
<iframe
|
||||
id="page-overlay"
|
||||
src="pages/configuration.html?v=b872bdc"></iframe>
|
||||
src="pages/configuration.html?v=ae8af5d"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -324,8 +325,8 @@
|
|||
<script src="js/lib/layers.js?v=a1f8aea" type="text/javascript"></script>
|
||||
<script src="js/lib/commands.js?v=00464cb" type="text/javascript"></script>
|
||||
|
||||
<script src="js/lib/toolbar.js?v=8a08072" type="text/javascript"></script>
|
||||
<script src="js/lib/ui.js?v=8481b85" type="text/javascript"></script>
|
||||
<script src="js/lib/toolbar.js?v=d483951" type="text/javascript"></script>
|
||||
<script src="js/lib/ui.js?v=76ede2b" type="text/javascript"></script>
|
||||
|
||||
<script
|
||||
src="js/initalize/layers.populate.js?v=c81f0a5"
|
||||
|
@ -336,7 +337,7 @@
|
|||
|
||||
<!-- Content -->
|
||||
<script src="js/prompt.js?v=7a1c68c" type="text/javascript"></script>
|
||||
<script src="js/index.js?v=dd80c92" type="text/javascript"></script>
|
||||
<script src="js/index.js?v=133b74b" type="text/javascript"></script>
|
||||
|
||||
<script
|
||||
src="js/ui/floating/history.js?v=fc92d14"
|
||||
|
@ -350,7 +351,7 @@
|
|||
src="js/ui/tool/generic.js?v=f1a19a4"
|
||||
type="text/javascript"></script>
|
||||
|
||||
<script src="js/ui/tool/dream.js?v=230e42e" type="text/javascript"></script>
|
||||
<script src="js/ui/tool/dream.js?v=832aa62" type="text/javascript"></script>
|
||||
<script
|
||||
src="js/ui/tool/maskbrush.js?v=1e8a893"
|
||||
type="text/javascript"></script>
|
||||
|
|
40
js/index.js
40
js/index.js
|
@ -531,6 +531,16 @@ const modelAutoComplete = createAutoComplete(
|
|||
"Model",
|
||||
document.getElementById("models-ac-select")
|
||||
);
|
||||
modelAutoComplete.onchange.on(({value}) => {
|
||||
if (value.toLowerCase().includes("inpainting"))
|
||||
document.querySelector(
|
||||
"#models-ac-select input.autocomplete-text"
|
||||
).style.backgroundColor = "#cfc";
|
||||
else
|
||||
document.querySelector(
|
||||
"#models-ac-select input.autocomplete-text"
|
||||
).style.backgroundColor = "#fcc";
|
||||
});
|
||||
|
||||
const samplerAutoComplete = createAutoComplete(
|
||||
"Sampler",
|
||||
|
@ -565,8 +575,8 @@ makeSlider(
|
|||
"CFG Scale",
|
||||
document.getElementById("cfgScale"),
|
||||
"cfg_scale",
|
||||
-1,
|
||||
25,
|
||||
localStorage.getItem("openoutpaint/settings.min-cfg") || 1,
|
||||
localStorage.getItem("openoutpaint/settings.max-cfg") || 25,
|
||||
0.5,
|
||||
7.0,
|
||||
0.1
|
||||
|
@ -600,7 +610,27 @@ makeSlider(
|
|||
0.1
|
||||
);
|
||||
|
||||
makeSlider("Steps", document.getElementById("steps"), "steps", 1, 70, 5, 30, 1);
|
||||
makeSlider(
|
||||
"Steps",
|
||||
document.getElementById("steps"),
|
||||
"steps",
|
||||
1,
|
||||
localStorage.getItem("openoutpaint/settings.max-steps") || 70,
|
||||
5,
|
||||
30,
|
||||
1
|
||||
);
|
||||
|
||||
makeSlider(
|
||||
"HRfix Lock Px.",
|
||||
document.getElementById("hrFixLock"),
|
||||
"hr_fix_lock_px",
|
||||
0.0,
|
||||
768.0,
|
||||
256.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
function changeMaskBlur() {
|
||||
stableDiffusionData.mask_blur = parseInt(
|
||||
|
@ -782,6 +812,10 @@ async function getModels() {
|
|||
modelAutoComplete.options = data.map((option) => ({
|
||||
name: option.title,
|
||||
value: option.title,
|
||||
optionelcb: (el) => {
|
||||
if (option.title.toLowerCase().includes("inpainting"))
|
||||
el.classList.add("inpainting");
|
||||
},
|
||||
}));
|
||||
|
||||
try {
|
||||
|
|
|
@ -188,4 +188,31 @@ const _toolbar_input = {
|
|||
},
|
||||
};
|
||||
},
|
||||
|
||||
selectlist: (
|
||||
state,
|
||||
dataKey,
|
||||
text,
|
||||
options = {value, text},
|
||||
defaultOptionValue,
|
||||
cb = null
|
||||
) => {
|
||||
const selectlist = document.createElement("select");
|
||||
selectlist.classList.add("bareselector");
|
||||
Object.entries(options).forEach((opt) => {
|
||||
var option = document.createElement("option");
|
||||
option.value = opt[0];
|
||||
option.text = opt[1];
|
||||
selectlist.options.add(option);
|
||||
});
|
||||
selectlist.selectedIndex = defaultOptionValue;
|
||||
selectlist.onchange = () => {
|
||||
state[dataKey] = selectlist.selectedIndex;
|
||||
cb && cb();
|
||||
};
|
||||
const label = document.createElement("label");
|
||||
label.appendChild(new Text(text));
|
||||
label.appendChild(selectlist);
|
||||
return {selectlist, label};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -206,7 +206,7 @@ function createSlider(name, wrapper, options = {}) {
|
|||
* @param {HTMLDivElement} wrapper The div element that will wrap the input elements
|
||||
* @param {object} options Extra options
|
||||
* @param {boolean} options.multiple Whether multiple options can be selected
|
||||
* @param {{name: string, value: string}[]} options.options Options to add to the selector
|
||||
* @param {{name: string, value: string, optionelcb: (el: HTMLOptionElement) => void}[]} options.options Options to add to the selector
|
||||
* @returns {AutoCompleteElement}
|
||||
*/
|
||||
function createAutoComplete(name, wrapper, options = {}) {
|
||||
|
@ -293,6 +293,7 @@ function createAutoComplete(name, wrapper, options = {}) {
|
|||
const optionEl = document.createElement("option");
|
||||
optionEl.classList.add("autocomplete-option");
|
||||
optionEl.title = title || name;
|
||||
if (opt.optionelcb) opt.optionelcb(optionEl);
|
||||
|
||||
const option = {name, value, optionElement: optionEl};
|
||||
|
||||
|
|
|
@ -375,12 +375,16 @@ const _generate = async (endpoint, request, bb, options = {}) => {
|
|||
});
|
||||
};
|
||||
|
||||
const sendInterrupt = () => {
|
||||
fetch(`${host}${config.api.path}interrupt`, {method: "POST"});
|
||||
};
|
||||
|
||||
// Add Interrupt Button
|
||||
const interruptButton = makeElement("button", bb.x + bb.w - 100, bb.y + bb.h);
|
||||
interruptButton.classList.add("dream-stop-btn");
|
||||
interruptButton.textContent = "Interrupt";
|
||||
interruptButton.addEventListener("click", () => {
|
||||
fetch(`${host}${config.api.path}interrupt`, {method: "POST"});
|
||||
sendInterrupt();
|
||||
interruptButton.disabled = true;
|
||||
});
|
||||
const marchingOptions = {};
|
||||
|
@ -390,6 +394,9 @@ const _generate = async (endpoint, request, bb, options = {}) => {
|
|||
console.info(`[dream] Generating images for prompt '${request.prompt}'`);
|
||||
console.debug(request);
|
||||
|
||||
eagerGenerateCount = toolbar._current_tool.state.eagerGenerateCount;
|
||||
isDreamComplete = false;
|
||||
|
||||
let stopProgress = null;
|
||||
try {
|
||||
let stopDrawingStatus = false;
|
||||
|
@ -428,6 +435,19 @@ const _generate = async (endpoint, request, bb, options = {}) => {
|
|||
imageCollection.inputElement.removeChild(interruptButton);
|
||||
}
|
||||
|
||||
const needMoreGenerations = () => {
|
||||
return (
|
||||
eagerGenerateCount > 0 &&
|
||||
images.length - highestNavigatedImageIndex <= eagerGenerateCount
|
||||
);
|
||||
};
|
||||
|
||||
const isGenerationPending = () => {
|
||||
return generationQueue.length > 0;
|
||||
};
|
||||
|
||||
let highestNavigatedImageIndex = 0;
|
||||
|
||||
// Image navigation
|
||||
const prevImg = () => {
|
||||
at--;
|
||||
|
@ -443,10 +463,16 @@ const _generate = async (endpoint, request, bb, options = {}) => {
|
|||
at++;
|
||||
if (at >= images.length) at = 0;
|
||||
|
||||
highestNavigatedImageIndex = Math.max(at, highestNavigatedImageIndex);
|
||||
|
||||
imageindextxt.textContent = `${at}/${images.length - 1}`;
|
||||
var seed = seeds[at];
|
||||
seedbtn.title = "Use seed " + seed;
|
||||
redraw();
|
||||
|
||||
if (needMoreGenerations() && !isGenerationPending()) {
|
||||
makeMore();
|
||||
}
|
||||
};
|
||||
|
||||
const applyImg = async () => {
|
||||
|
@ -504,6 +530,11 @@ const _generate = async (endpoint, request, bb, options = {}) => {
|
|||
}
|
||||
|
||||
nextQueue(moreQ);
|
||||
|
||||
//Start the next batch if we're eager-generating
|
||||
if (needMoreGenerations() && !isGenerationPending() && !isDreamComplete) {
|
||||
makeMore();
|
||||
}
|
||||
};
|
||||
|
||||
const discardImg = async () => {
|
||||
|
@ -657,6 +688,10 @@ const _generate = async (endpoint, request, bb, options = {}) => {
|
|||
mouse.listen.world.btn.right.onclick.clear(oncancelhandler);
|
||||
mouse.listen.world.btn.middle.onclick.clear(onmorehandler);
|
||||
mouse.listen.world.onwheel.clear(onwheelhandler);
|
||||
isDreamComplete = true;
|
||||
if (generating) {
|
||||
sendInterrupt();
|
||||
}
|
||||
};
|
||||
|
||||
redraw();
|
||||
|
@ -740,6 +775,11 @@ const _generate = async (endpoint, request, bb, options = {}) => {
|
|||
imageSelectMenu.appendChild(seedbtn);
|
||||
|
||||
nextQueue(initialQ);
|
||||
|
||||
//Start the next batch after the initial generation
|
||||
if (needMoreGenerations()) {
|
||||
makeMore();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -932,7 +972,7 @@ const dream_img2img_callback = (bb, resolution, state) => {
|
|||
request.height = resolution.h;
|
||||
|
||||
request.denoising_strength = state.denoisingStrength;
|
||||
request.inpainting_fill = 1; // For img2img use original
|
||||
request.inpainting_fill = state.inpainting_fill; //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;
|
||||
|
@ -1186,6 +1226,7 @@ const dreamTool = () =>
|
|||
state.keepUnmaskedBlur = 8;
|
||||
state.overMaskPx = 20;
|
||||
state.preserveMasks = false;
|
||||
state.eagerGenerateCount = 0;
|
||||
|
||||
state.erasePrevCursor = () =>
|
||||
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
||||
|
@ -1346,6 +1387,18 @@ 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 {
|
||||
|
@ -1477,6 +1530,19 @@ const dreamTool = () =>
|
|||
textStep: 1,
|
||||
}
|
||||
).slider;
|
||||
|
||||
// Eager generation Slider
|
||||
state.ctxmenu.eagerGenerateCountLabel = _toolbar_input.slider(
|
||||
state,
|
||||
"eagerGenerateCount",
|
||||
"Generate-ahead count",
|
||||
{
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 2,
|
||||
textStep: 1,
|
||||
}
|
||||
).slider;
|
||||
}
|
||||
|
||||
menu.appendChild(state.ctxmenu.cursorSizeSlider);
|
||||
|
@ -1489,6 +1555,7 @@ const dreamTool = () =>
|
|||
menu.appendChild(state.ctxmenu.preserveMasksLabel);
|
||||
menu.appendChild(document.createElement("br"));
|
||||
menu.appendChild(state.ctxmenu.overMaskPxLabel);
|
||||
menu.appendChild(state.ctxmenu.eagerGenerateCountLabel);
|
||||
},
|
||||
shortcut: "D",
|
||||
}
|
||||
|
@ -1573,6 +1640,7 @@ const img2imgTool = () =>
|
|||
state.keepUnmaskedBlur = 8;
|
||||
state.fullResolution = false;
|
||||
state.preserveMasks = false;
|
||||
state.eagerGenerateCount = 0;
|
||||
|
||||
state.denoisingStrength = 0.7;
|
||||
|
||||
|
@ -2006,6 +2074,36 @@ const img2imgTool = () =>
|
|||
textStep: 1,
|
||||
}
|
||||
).slider;
|
||||
|
||||
// inpaint fill type select list
|
||||
state.ctxmenu.inpaintTypeSelect = _toolbar_input.selectlist(
|
||||
state,
|
||||
"inpainting_fill",
|
||||
"Inpaint Type",
|
||||
{
|
||||
0: "fill",
|
||||
1: "original (recommended)",
|
||||
2: "latent noise",
|
||||
3: "latent nothing",
|
||||
},
|
||||
1, // USE ORIGINAL FOR IMG2IMG OR ELSE but we still give you the option because we love you
|
||||
() => {
|
||||
stableDiffusionData.inpainting_fill = state.inpainting_fill;
|
||||
}
|
||||
).label;
|
||||
|
||||
// Eager generation Slider
|
||||
state.ctxmenu.eagerGenerateCountLabel = _toolbar_input.slider(
|
||||
state,
|
||||
"eagerGenerateCount",
|
||||
"Generate-ahead count",
|
||||
{
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 2,
|
||||
textStep: 1,
|
||||
}
|
||||
).slider;
|
||||
}
|
||||
|
||||
menu.appendChild(state.ctxmenu.cursorSizeSlider);
|
||||
|
@ -2020,9 +2118,11 @@ const img2imgTool = () =>
|
|||
menu.appendChild(document.createElement("br"));
|
||||
menu.appendChild(state.ctxmenu.fullResolutionLabel);
|
||||
menu.appendChild(document.createElement("br"));
|
||||
menu.appendChild(state.ctxmenu.inpaintTypeSelect);
|
||||
menu.appendChild(state.ctxmenu.denoisingStrengthSlider);
|
||||
menu.appendChild(state.ctxmenu.borderMaskGradientCheckbox);
|
||||
menu.appendChild(state.ctxmenu.borderMaskSlider);
|
||||
menu.appendChild(state.ctxmenu.eagerGenerateCountLabel);
|
||||
},
|
||||
shortcut: "I",
|
||||
}
|
||||
|
@ -2030,8 +2130,7 @@ const img2imgTool = () =>
|
|||
|
||||
window.onbeforeunload = async () => {
|
||||
// Stop current generation on page close
|
||||
if (generating)
|
||||
await fetch(`${host}${config.api.path}interrupt`, {method: "POST"});
|
||||
if (generating) await sendInterrupt();
|
||||
};
|
||||
|
||||
const sendSeed = (seed) => {
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
<link href="../css/colors.css?v=3f81e80" rel="stylesheet" />
|
||||
<link href="../css/icons.css?v=a25504c" rel="stylesheet" />
|
||||
|
||||
<link href="../css/index.css?v=ef0c943" rel="stylesheet" />
|
||||
<link href="../css/index.css?v=69d3b9e" rel="stylesheet" />
|
||||
<link href="../css/layers.css?v=b4fbf61" rel="stylesheet" />
|
||||
|
||||
<link href="../css/ui/generic.css?v=a15ce4b" rel="stylesheet" />
|
||||
<link href="../css/ui/generic.css?v=79bee9b" rel="stylesheet" />
|
||||
|
||||
<link href="../css/ui/history.css?v=0b03861" rel="stylesheet" />
|
||||
<link href="../css/ui/layers.css?v=4fd95fe" rel="stylesheet" />
|
||||
|
@ -59,10 +59,39 @@
|
|||
type="number"
|
||||
step="1" />
|
||||
</label>
|
||||
<label style="display: flex">
|
||||
Max Steps:
|
||||
<input
|
||||
id="max-steps"
|
||||
class="canvas-size-input"
|
||||
type="number"
|
||||
step="1"
|
||||
value="70" />
|
||||
</label>
|
||||
<label style="display: flex">
|
||||
CFG minmax:
|
||||
<input
|
||||
id="min-cfg"
|
||||
class="canvas-size-input"
|
||||
type="number"
|
||||
step="0.1"
|
||||
value="-1.0" />
|
||||
::
|
||||
<input
|
||||
id="max-cfg"
|
||||
class="canvas-size-input"
|
||||
type="number"
|
||||
step="0.1"
|
||||
value="30.0" />
|
||||
</label>
|
||||
<p>Refresh the page to apply settings.</p>
|
||||
|
||||
<script>
|
||||
const canvasWidth = document.getElementById("canvas-width");
|
||||
const canvasHeight = document.getElementById("canvas-height");
|
||||
const maxSteps = document.getElementById("max-steps");
|
||||
const minCfg = document.getElementById("min-cfg");
|
||||
const maxCfg = document.getElementById("max-cfg");
|
||||
|
||||
function writeToLocalStorage() {
|
||||
localStorage.setItem(
|
||||
|
@ -73,6 +102,9 @@
|
|||
"openoutpaint/settings.canvas-height",
|
||||
canvasHeight.value
|
||||
);
|
||||
localStorage.setItem("openoutpaint/settings.max-steps", maxSteps.value);
|
||||
localStorage.setItem("openoutpaint/settings.min-cfg", minCfg.value);
|
||||
localStorage.setItem("openoutpaint/settings.max-cfg", maxCfg.value);
|
||||
}
|
||||
|
||||
// Loads values from local storage
|
||||
|
@ -80,11 +112,20 @@
|
|||
localStorage.getItem("openoutpaint/settings.canvas-width") || 2048;
|
||||
canvasHeight.value =
|
||||
localStorage.getItem("openoutpaint/settings.canvas-height") || 2048;
|
||||
maxSteps.value =
|
||||
localStorage.getItem("openoutpaint/settings.max-steps") || 70;
|
||||
minCfg.value =
|
||||
localStorage.getItem("openoutpaint/settings.min-cfg") || -1;
|
||||
maxCfg.value =
|
||||
localStorage.getItem("openoutpaint/settings.max-cfg") || 30;
|
||||
|
||||
writeToLocalStorage();
|
||||
|
||||
canvasWidth.onchange = writeToLocalStorage;
|
||||
canvasHeight.onchange = writeToLocalStorage;
|
||||
maxSteps.onchange = writeToLocalStorage;
|
||||
minCfg.onchange = writeToLocalStorage;
|
||||
maxCfg.onchange = writeToLocalStorage;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
id="openoutpaint"
|
||||
style="width: 100%; height: 800px"
|
||||
src="../index.html?v=e2520a0"
|
||||
src="../index.html?v=49afaa2"
|
||||
frameborder="0"></iframe>
|
||||
<button id="add-res">Add Resource</button>
|
||||
<script>
|
||||
|
|
Loading…
Reference in a new issue