From a1cdda849cc2f035ea6ea04c45d1887d6f9bcf9b Mon Sep 17 00:00:00 2001 From: hnmr293 Date: Sat, 1 Apr 2023 18:59:00 +0900 Subject: [PATCH] fix for webui update #26, #27, #29 --- javascript/lazyload/posex-webui.js | 60 ++++++++----- javascript/posex-webui.js | 137 +++++++++++++++++------------ scripts/posex.py | 2 +- 3 files changed, 119 insertions(+), 80 deletions(-) diff --git a/javascript/lazyload/posex-webui.js b/javascript/lazyload/posex-webui.js index 6b26c86..819c139 100644 --- a/javascript/lazyload/posex-webui.js +++ b/javascript/lazyload/posex-webui.js @@ -1,5 +1,3 @@ -console.log('[Posex] loading...'); - async function _import() { if (!globalThis.posex || !globalThis.posex.import) { return await import('posex'); @@ -329,6 +327,7 @@ const { init, init_3d } = await _import(); animate(); onUiTabChange(() => { + debugger; const tabname = get_uiCurrentTabContent().id; if (type === 't2i') { if (0 <= tabname.indexOf('txt2img')) { @@ -348,25 +347,40 @@ const { init, init_3d } = await _import(); }); } - const app = gradioApp(); - await init_canvas( - 't2i', - app.querySelector('#posex-t2i-enabled input[type=checkbox]'), - app.querySelector('#txt2img_generate'), - app.querySelector('#posex-t2i-html'), - { - load_all_poses: app.querySelector('#posex-t2i-api-all_pose'), - delete_pose: app.querySelector('#posex-t2i-api-delete_pose'), - } - ); - await init_canvas( - 'i2i', - app.querySelector('#posex-i2i-enabled input[type=checkbox]'), - app.querySelector('#img2img_generate'), - app.querySelector('#posex-i2i-html'), - { - load_all_poses: app.querySelector('#posex-i2i-api-all_pose'), - delete_pose: app.querySelector('#posex-i2i-api-delete_pose'), - } - ); + async function init_t2i() { + const app = gradioApp(); + await init_canvas( + 't2i', + app.querySelector('#posex-t2i-enabled input[type=checkbox]'), + app.querySelector('#txt2img_generate'), + app.querySelector('#posex-t2i-html'), + { + load_all_poses: app.querySelector('#posex-t2i-api-all_pose'), + delete_pose: app.querySelector('#posex-t2i-api-delete_pose'), + } + ); + } + + async function init_i2i() { + const app = gradioApp(); + await init_canvas( + 'i2i', + app.querySelector('#posex-i2i-enabled input[type=checkbox]'), + app.querySelector('#img2img_generate'), + app.querySelector('#posex-i2i-html'), + { + load_all_poses: app.querySelector('#posex-i2i-api-all_pose'), + delete_pose: app.querySelector('#posex-i2i-api-delete_pose'), + } + ); + } + + if (!globalThis.posex) globalThis.posex = {}; + const posex = globalThis.posex; + posex.init_t2i = init_t2i; + posex.init_i2i = init_i2i; + + posex.script_loaded = true; + document.dispatchEvent(new CustomEvent('posexscriptloaded')); + })(); diff --git a/javascript/posex-webui.js b/javascript/posex-webui.js index 75e918c..0e95bb1 100644 --- a/javascript/posex-webui.js +++ b/javascript/posex-webui.js @@ -3,67 +3,92 @@ const posex = globalThis.posex; function load(cont) { - const scripts = cont.textContent.trim().split('\n'); - const base_path = `/file=${scripts.shift()}/js`; - cont.textContent = ''; + function load_() { + if (posex.script_loading || posex.script_loaded) return; + posex.script_loading = true; + + const scripts = cont.textContent.trim().split('\n'); + const base_path = `/file=${scripts.shift()}/js`; + cont.textContent = ''; - const df = document.createDocumentFragment(); - for (let src of scripts) { - const script = document.createElement('script'); - script.async = true; - script.type = 'module'; - script.src = `file=${src}`; - df.appendChild(script); + const df = document.createDocumentFragment(); + for (let src of scripts) { + console.log(`[Posex] loading ${src}`); + const script = document.createElement('script'); + script.async = true; + script.type = 'module'; + script.src = `file=${src}`; + df.appendChild(script); + } + + globalThis.posex.import = async () => { + const THREE = await import(`${base_path}/three.module.js`); + const { TrackballControls } = await import(`${base_path}/TrackballControls.js`); + const { DragControls } = await import(`${base_path}/DragControls.js`); + const { MeshLine, MeshLineMaterial } = await import(`${base_path}/THREE.MeshLine.Module.min.js`); + return { THREE, TrackballControls, DragControls, MeshLine, MeshLineMaterial }; + }; + if (!globalThis.posex.imports) globalThis.posex.imports = {}; + if (!globalThis.posex.imports.three) globalThis.posex.imports.three = async () => await import(`${base_path}/three.module.js`); + if (!globalThis.posex.imports.posex) globalThis.posex.imports.posex = async () => await import(`${base_path}/posex.js`); + cont.appendChild(df); } - globalThis.posex.import = async () => { - const THREE = await import(`${base_path}/three.module.js`); - const { TrackballControls } = await import(`${base_path}/TrackballControls.js`); - const { DragControls } = await import(`${base_path}/DragControls.js`); - const { MeshLine, MeshLineMaterial } = await import(`${base_path}/THREE.MeshLine.Module.min.js`); - return { THREE, TrackballControls, DragControls, MeshLine, MeshLineMaterial }; - }; - if (!globalThis.posex.imports) globalThis.posex.imports = {}; - if (!globalThis.posex.imports.three) globalThis.posex.imports.three = async () => await import(`${base_path}/three.module.js`); - if (!globalThis.posex.imports.posex) globalThis.posex.imports.posex = async () => await import(`${base_path}/posex.js`); - cont.appendChild(df); + return posex.script_loaded ? Promise.resolve() : new Promise(resolve => { + document.addEventListener('posexscriptloaded', () => resolve(), false); + load_(); + }); } - onUiUpdate(() => { - const app = gradioApp(); - if (!app || app === document) return; - - const t2i_cont = app.querySelector('#posex-t2i-js') - const i2i_cont = app.querySelector('#posex-i2i-js') - if (!t2i_cont || !i2i_cont) return; - - const t2i_enabled = app.querySelector('#posex-t2i-enabled input[type=checkbox]'); - const i2i_enabled = app.querySelector('#posex-i2i-enabled input[type=checkbox]'); - - const t2i_callback = () => { - if (!posex.t2i_called) { - posex.t2i_called = true; - load(t2i_cont); + function lazy(fn, timeout) { + if (timeout === undefined) timeout = 500; + return new Promise(function callback(resolve) { + const result = fn(); + if (result) { + resolve(result); + } else { + setTimeout(() => callback(resolve), timeout); } - }; - - const i2i_callback = () => { - if (!posex.t2i_called) { - posex.t2i_called = true; - load(t2i_cont); + }); + } + + function hook_acc(acc, fn) { + const observer = new MutationObserver(list => { + for (let mut of list) { + if (mut.type === 'childList') { + if (mut.addedNodes.length != 0) { + // closed -> opened + fn(); + } else { + // opened -> closed + // do nothing + } + } } - }; - - if (t2i_enabled.checked) { - t2i_callback(); - } else { - t2i_enabled.addEventListener('change', t2i_callback, false); - } - - if (i2i_enabled.checked) { - i2i_callback(); - } else { - i2i_enabled.addEventListener('change', i2i_callback, false); - } - }); + }); + observer.observe(acc, { childList: true, attributes: false, subtree: false }); + } + + function launch(type) { + return lazy(() => gradioApp()?.querySelector(`#posex-${type}-accordion`)). + then(acc => hook_acc(acc, async () => { + const cont = acc.querySelector(`#posex-${type}-js`); + const enabled = acc.querySelector(`#posex-${type}-enabled input[type=checkbox]`); + if (enabled.checked) { + await load(cont); + await posex[`init_${type}`](); + console.log(`[Posex] ${type} initialized`); + } else { + enabled.addEventListener('change', async () => { + await load(cont); + await posex[`init_${type}`](); + console.log(`[Posex] ${type} initialized`); + }, { once: true }); + } + })); + } + + launch('t2i').then(() => console.log('[Posex] t2i initialized')); + launch('i2i').then(() => console.log('[Posex] i2i initialized')); + })(); diff --git a/scripts/posex.py b/scripts/posex.py index 89a389b..9bdeb83 100644 --- a/scripts/posex.py +++ b/scripts/posex.py @@ -37,7 +37,7 @@ def ui(self, is_img2img): js_ = [f'{x.path}?{os.path.getmtime(x.path)}' for x in ext.list_files('javascript/lazyload', '.js')] js_.insert(0, ext.path) - with gr.Accordion('Posex', open=False): + with gr.Accordion('Posex', open=False, elem_id=id('accordion')): with gr.Row(): enabled = gr.Checkbox(value=False, label='Send this image to ControlNet.', elem_id=id('enabled')) cn_num = gr.Number(value=0, precision=0, label='Target ControlNet number', visible=self.max_cn_num()!=1)