Merge pull request #10 from ilian6806/develop

Control net support
pull/11/head
Ilian Iliev 2023-03-30 09:16:41 +03:00 committed by GitHub
commit d30b88581f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 289 additions and 56 deletions

4
javascript/state.app.js Normal file
View File

@ -0,0 +1,4 @@
document.addEventListener('DOMContentLoaded', function() {
onUiLoaded(state.core.init);
});

View File

@ -0,0 +1,5 @@
window.state = window.state || {};
state.constants = {
LS_PREFIX: 'state-'
};

View File

@ -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 };
}());

View File

@ -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 };
}());

30
javascript/state.store.js Normal file
View File

@ -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]);
}
}
};

56
javascript/state.utils.js Normal file
View File

@ -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));
}
};

View File

@ -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)