Merge pull request #9 from ilian6806/feature/control-net-support
Feature/control net supportpull/10/head
commit
aa3ff584f0
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
onUiLoaded(state.core.init);
|
||||
});
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
window.state = window.state || {};
|
||||
|
||||
state.constants = {
|
||||
LS_PREFIX: 'state-'
|
||||
};
|
||||
|
|
@ -1,12 +1,7 @@
|
|||
window.state = window.state || {};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
onUiLoaded(StateController.init);
|
||||
});
|
||||
state.core = (function () {
|
||||
|
||||
|
||||
const StateController = (function () {
|
||||
|
||||
const LS_PREFIX = 'state-';
|
||||
const TABS = ['txt2img', 'img2img'];
|
||||
const ELEMENTS = {
|
||||
'prompt': 'prompt',
|
||||
|
|
@ -35,13 +30,7 @@ const StateController = (function () {
|
|||
'resize_mode': 'resize_mode',
|
||||
};
|
||||
|
||||
function triggerEvent(element, event) {
|
||||
if (! element) {
|
||||
return;
|
||||
}
|
||||
element.dispatchEvent(new Event(event.trim()));
|
||||
return element;
|
||||
}
|
||||
let store = null;
|
||||
|
||||
function hasSetting(id, tab) {
|
||||
const suffix = tab ? `_${tab}` : '';
|
||||
|
|
@ -64,6 +53,8 @@ const StateController = (function () {
|
|||
|
||||
function load(config) {
|
||||
|
||||
store = new state.Store();
|
||||
|
||||
loadUI();
|
||||
restoreTabs(config);
|
||||
|
||||
|
|
@ -82,20 +73,8 @@ const StateController = (function () {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function storeTab() {
|
||||
localStorage.setItem(LS_PREFIX + 'tab', this.textContent);
|
||||
bindTabEvents();
|
||||
}
|
||||
|
||||
function bindTabEvents() {
|
||||
const tabs = gradioApp().querySelectorAll('#tabs > div:first-child button');
|
||||
tabs.forEach(tab => { // dirty hack here
|
||||
tab.removeEventListener('click', storeTab);
|
||||
tab.addEventListener('click', storeTab);
|
||||
});
|
||||
return tabs;
|
||||
handleExtensions(config);
|
||||
}
|
||||
|
||||
function loadUI() {
|
||||
|
|
@ -112,12 +91,7 @@ const StateController = (function () {
|
|||
resetBtn.addEventListener('click', function () {
|
||||
let confirmed = confirm('Reset all state values?');
|
||||
if (confirmed) {
|
||||
let keys = Object.keys(localStorage);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (keys[i].startsWith('state-')) {
|
||||
localStorage.removeItem(keys[i]);
|
||||
}
|
||||
}
|
||||
store.clearAll();
|
||||
alert('All state values deleted!');
|
||||
}
|
||||
});
|
||||
|
|
@ -135,17 +109,21 @@ const StateController = (function () {
|
|||
return;
|
||||
}
|
||||
|
||||
const tabs = bindTabEvents();
|
||||
const value = localStorage.getItem(LS_PREFIX + 'tab');
|
||||
const tabs = gradioApp().querySelectorAll('#tabs > div:first-child button');
|
||||
const value = store.get('tab');
|
||||
|
||||
if (value) {
|
||||
for (var i = 0; i < tabs.length; i++) {
|
||||
if (tabs[i].textContent === value) {
|
||||
triggerEvent(tabs[i], 'click');
|
||||
state.utils.triggerEvent(tabs[i], 'click');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onUiTabChange(function () {
|
||||
store.set('tab', get_uiCurrentTab().textContent);
|
||||
});
|
||||
}
|
||||
|
||||
function handleSavedInput(id) {
|
||||
|
|
@ -171,7 +149,7 @@ const StateController = (function () {
|
|||
if (this.type && this.type === 'checkbox') {
|
||||
value = this.checked;
|
||||
}
|
||||
localStorage.setItem(LS_PREFIX + id, value);
|
||||
store.set(id, value);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -181,38 +159,32 @@ const StateController = (function () {
|
|||
const btn = gradioApp().querySelector(`#${tab}_${id}`);
|
||||
btn.addEventListener('click', () => {
|
||||
setTimeout(() => {
|
||||
triggerEvent(seedInput, 'change');
|
||||
state.utils.triggerEvent(seedInput, 'change');
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let value = localStorage.getItem(LS_PREFIX + id);
|
||||
let value = store.get(id);
|
||||
|
||||
if (! value) {
|
||||
return;
|
||||
}
|
||||
|
||||
forEach(function (event) {
|
||||
switch (this.type) {
|
||||
case 'checkbox':
|
||||
this.checked = value === 'true';
|
||||
triggerEvent(this, event);
|
||||
break;
|
||||
case 'radio':
|
||||
if (this.value === value) {
|
||||
this.checked = true;
|
||||
triggerEvent(this, event);
|
||||
} else {
|
||||
this.checked = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.value = value;
|
||||
triggerEvent(this, event);
|
||||
}
|
||||
state.utils.setValue(this, value, event);
|
||||
});
|
||||
}
|
||||
|
||||
function handleExtensions(config) {
|
||||
if (config['state_extensions']) {
|
||||
config['state_extensions'].forEach(function (ext) {
|
||||
if (ext in state.extensions) {
|
||||
state.extensions[ext].init();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { init };
|
||||
}());
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
window.state = window.state || {};
|
||||
window.state.extensions = window.state.extensions || {};
|
||||
|
||||
state.extensions['control-net'] = (function () {
|
||||
|
||||
let container = null;
|
||||
let store = null;
|
||||
let cnTabs = [];
|
||||
|
||||
function handleToggle() {
|
||||
let value = store.get('toggled');
|
||||
let toggleBtn = container.querySelector('div.cursor-pointer');
|
||||
if (value && value === 'true') {
|
||||
state.utils.triggerEvent(toggleBtn, 'click');
|
||||
}
|
||||
toggleBtn.addEventListener('click', function () {
|
||||
let span = this.querySelector('.transition');
|
||||
store.set('toggled', !span.classList.contains('rotate-90'));
|
||||
});
|
||||
}
|
||||
|
||||
function bindTabEvents() {
|
||||
const tabs = container.querySelectorAll('.tabs > div > button');
|
||||
tabs.forEach(tab => { // dirty hack here
|
||||
tab.removeEventListener('click', onTabClick);
|
||||
tab.addEventListener('click', onTabClick);
|
||||
});
|
||||
return tabs;
|
||||
}
|
||||
|
||||
function handleTabs() {
|
||||
let tabs = bindTabEvents();
|
||||
let value = store.get('tab');
|
||||
if (value) {
|
||||
for (var i = 0; i < tabs.length; i++) {
|
||||
if (tabs[i].textContent === value) {
|
||||
state.utils.triggerEvent(tabs[i], 'click');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onTabClick() {
|
||||
store.set('tab', this.textContent);
|
||||
bindTabEvents();
|
||||
}
|
||||
|
||||
function handleCheckboxes() {
|
||||
cnTabs.forEach(({ container, store }) => {
|
||||
let checkboxes = container.querySelectorAll('input[type="checkbox"]');
|
||||
checkboxes.forEach(function (checkbox) {
|
||||
let label = checkbox.nextElementSibling;
|
||||
let id = state.utils.txtToId(label.textContent);
|
||||
let value = store.get(id);
|
||||
if (value) {
|
||||
state.utils.setValue(checkbox, value, 'change');
|
||||
}
|
||||
checkbox.addEventListener('change', function () {
|
||||
store.set(id, this.checked);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleSelects() {
|
||||
cnTabs.forEach(({ container, store }) => {
|
||||
let selects = container.querySelectorAll('select');
|
||||
selects.forEach(function (select) {
|
||||
let label = select.previousElementSibling;
|
||||
let id = state.utils.txtToId(label.textContent);
|
||||
let value = store.get(id);
|
||||
if (value) {
|
||||
state.utils.setValue(select, value, 'change');
|
||||
}
|
||||
select.addEventListener('change', function () {
|
||||
store.set(id, this.value);
|
||||
});
|
||||
if (id === 'preprocessor' && value && value !== 'none') {
|
||||
state.utils.onNextUiUpdates(handleSliders); // update new sliders if needed
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleSliders() {
|
||||
cnTabs.forEach(({ container, store }) => {
|
||||
let sliders = container.querySelectorAll('input[type="range"]');
|
||||
sliders.forEach(function (slider) {
|
||||
let label = slider.previousElementSibling.querySelector('label span');
|
||||
let id = state.utils.txtToId(label.textContent);
|
||||
let value = store.get(id);
|
||||
if (value) {
|
||||
state.utils.setValue(slider, value, 'change');
|
||||
}
|
||||
slider.addEventListener('change', function () {
|
||||
store.set(id, this.value);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleRadioButtons() {
|
||||
cnTabs.forEach(({ container, store }) => {
|
||||
let fieldsets = container.querySelectorAll('fieldset');
|
||||
fieldsets.forEach(function (fieldset) {
|
||||
let label = fieldset.firstChild.nextElementSibling;
|
||||
let radios = fieldset.querySelectorAll('input[type="radio"]');
|
||||
let id = state.utils.txtToId(label.textContent);
|
||||
let value = store.get(id);
|
||||
if (value) {
|
||||
radios.forEach(function (radio) {
|
||||
state.utils.setValue(radio, value, 'change');
|
||||
});
|
||||
}
|
||||
radios.forEach(function (radio) {
|
||||
radio.addEventListener('change', function () {
|
||||
store.set(id, this.value);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function load() {
|
||||
handleToggle();
|
||||
handleTabs();
|
||||
handleCheckboxes();
|
||||
handleSelects();
|
||||
handleSliders();
|
||||
handleRadioButtons();
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
container = gradioApp().getElementById('controlnet');
|
||||
store = new state.Store('ext-control-net');
|
||||
|
||||
let tabs = container.querySelectorAll('.tabitem');
|
||||
|
||||
if (tabs.length) {
|
||||
cnTabs = [];
|
||||
tabs.forEach((tabContainer, i) => {
|
||||
cnTabs.push({
|
||||
container: tabContainer,
|
||||
store: new state.Store('ext-control-net-' + i)
|
||||
});
|
||||
});
|
||||
} else {
|
||||
cnTabs = [{
|
||||
container: container,
|
||||
store: new state.Store('ext-control-net-0')
|
||||
}];
|
||||
}
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
return { init };
|
||||
}());
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
window.state = window.state || {};
|
||||
|
||||
state.Store = function Store (prefix) {
|
||||
this.prefix = state.constants.LS_PREFIX + (prefix ? prefix + '-' : '');
|
||||
}
|
||||
|
||||
state.Store.prototype.set = function(key, value) {
|
||||
localStorage.setItem(this.prefix + key, value);
|
||||
};
|
||||
|
||||
state.Store.prototype.get = function(key) {
|
||||
return localStorage.getItem(this.prefix + key);
|
||||
};
|
||||
|
||||
state.Store.prototype.remove = function(key) {
|
||||
localStorage.removeItem(this.prefix + key);
|
||||
};
|
||||
|
||||
state.Store.prototype.clear = function() {
|
||||
localStorage.clear();
|
||||
};
|
||||
|
||||
state.Store.prototype.clearAll = function () {
|
||||
let keys = Object.keys(localStorage);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (keys[i].startsWith(state.constants.LS_PREFIX)) {
|
||||
localStorage.removeItem(keys[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
window.state = window.state || {};
|
||||
|
||||
state.utils = {
|
||||
triggerEvent: function triggerEvent(element, event) {
|
||||
if (! element) {
|
||||
return;
|
||||
}
|
||||
element.dispatchEvent(new Event(event.trim()));
|
||||
return element;
|
||||
},
|
||||
setValue: function setValue(element, value, event) {
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
element.checked = value === 'true';
|
||||
this.triggerEvent(element, event);
|
||||
break;
|
||||
case 'radio':
|
||||
if (element.value === value) {
|
||||
element.checked = true;
|
||||
this.triggerEvent(element, event);
|
||||
} else {
|
||||
element.checked = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
element.value = value;
|
||||
this.triggerEvent(element, event);
|
||||
}
|
||||
},
|
||||
txtToId: function txtToId(txt) {
|
||||
return txt.split(' ').join('-').toLowerCase();
|
||||
},
|
||||
callXTimes: function callXTimes(func, times) {
|
||||
let called = 0;
|
||||
return function() {
|
||||
if (called < times) {
|
||||
called++;
|
||||
return func.apply(this);
|
||||
}
|
||||
}
|
||||
},
|
||||
debounce: function debounce(func, delay) {
|
||||
let lastCallTime = 0;
|
||||
return function() {
|
||||
const currentCallTime = new Date().getTime();
|
||||
if (currentCallTime - lastCallTime > delay) {
|
||||
lastCallTime = currentCallTime;
|
||||
func.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
},
|
||||
onNextUiUpdates: function (func) {
|
||||
// brute force this to to ensure that the method is called after next few updates
|
||||
onUiUpdate(this.callXTimes(function () { setTimeout(func, 10); }, 50));
|
||||
}
|
||||
};
|
||||
|
|
@ -56,5 +56,11 @@ def on_ui_settings():
|
|||
]
|
||||
}, section=section))
|
||||
|
||||
shared.opts.add_option("state_extensions", shared.OptionInfo([], "Saved elements from extensions", gr.CheckboxGroup, lambda: {
|
||||
"choices": [
|
||||
"control-net"
|
||||
]
|
||||
}, section=section))
|
||||
|
||||
|
||||
scripts.script_callbacks.on_ui_settings(on_ui_settings)
|
||||
|
|
|
|||
Loading…
Reference in New Issue