Spaces:
Paused
Paused
File size: 6,718 Bytes
3f9c56c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
(function () {
async function checkEditorAvailable() {
const LOCAL_EDITOR_PATH = '/openpose_editor_index';
const REMOTE_EDITOR_PATH = 'https://huchenlei.github.io/sd-webui-openpose-editor/';
async function testEditorPath(path) {
const res = await fetch(path);
return res.status === 200 ? path : undefined;
}
// Use local editor if the user has the extension installed. Fallback
// onto remote editor if the local editor is not ready yet.
// See https://github.com/huchenlei/sd-webui-openpose-editor/issues/53
// for more details.
return await testEditorPath(LOCAL_EDITOR_PATH) || await testEditorPath(REMOTE_EDITOR_PATH);
}
const cnetOpenposeEditorRegisteredElements = new Set();
function loadOpenposeEditor(editorURL) {
// Simulate an `input` DOM event for Gradio Textbox component. Needed after you edit its contents in javascript, otherwise your edits
// will only visible on web page and not sent to python.
function updateInput(target) {
let e = new Event("input", { bubbles: true })
Object.defineProperty(e, "target", { value: target })
target.dispatchEvent(e);
}
function navigateIframe(iframe) {
function getPathname(rawURL) {
try {
return new URL(rawURL).pathname;
} catch (e) {
return rawURL;
}
}
return new Promise((resolve) => {
const darkThemeParam = document.body.classList.contains('dark') ?
new URLSearchParams({ theme: 'dark' }).toString() :
'';
window.addEventListener('message', (event) => {
const message = event.data;
if (message['ready']) resolve();
}, { once: true });
if (getPathname(iframe.src) !== editorURL) {
iframe.src = `${editorURL}?${darkThemeParam}`;
// By default assume 5 second is enough for the openpose editor
// to load.
setTimeout(resolve, 5000);
} else {
// If no navigation is required, immediately return.
resolve();
}
});
}
const imageRows = gradioApp().querySelectorAll('.cnet-image-row');
imageRows.forEach(imageRow => {
if (cnetOpenposeEditorRegisteredElements.has(imageRow)) return;
cnetOpenposeEditorRegisteredElements.add(imageRow);
const generatedImageGroup = imageRow.querySelector('.cnet-generated-image-group');
const editButton = generatedImageGroup.querySelector('.cnet-edit-pose');
editButton.addEventListener('click', async () => {
const inputImageGroup = imageRow.querySelector('.cnet-input-image-group');
const inputImage = inputImageGroup.querySelector('.cnet-image img');
const downloadLink = generatedImageGroup.querySelector('.cnet-download-pose a');
const modalId = editButton.id.replace('cnet-modal-open-', '');
const modalIframe = generatedImageGroup.querySelector('.cnet-modal iframe');
await navigateIframe(modalIframe);
modalIframe.contentWindow.postMessage({
modalId,
imageURL: inputImage.src,
poseURL: downloadLink.href,
}, '*');
// Focus the iframe so that the focus is no longer on the `Edit` button.
// Pressing space when the focus is on `Edit` button will trigger
// the click again to resend the frame message.
modalIframe.contentWindow.focus();
});
window.addEventListener('message', (event) => {
const message = event.data;
const downloadLink = generatedImageGroup.querySelector('.cnet-download-pose a');
const renderButton = generatedImageGroup.querySelector('.cnet-render-pose');
const poseTextbox = generatedImageGroup.querySelector('.cnet-pose-json textarea');
const modalId = editButton.id.replace('cnet-modal-open-', '');
const closeModalButton = generatedImageGroup.querySelector('.cnet-modal .cnet-modal-close');
if (message.modalId !== modalId) return;
/*
* Writes the pose data URL to an link element on input image group.
* Click a hidden button to trigger a backend rendering of the pose JSON.
*
* The backend should:
* - Set the rendered pose image as preprocessor generated image.
*/
downloadLink.href = message.poseURL;
poseTextbox.value = message.poseURL;
updateInput(poseTextbox);
renderButton.click();
closeModalButton.click();
});
});
}
function loadPlaceHolder() {
const imageRows = gradioApp().querySelectorAll('.cnet-image-row');
imageRows.forEach(imageRow => {
if (cnetOpenposeEditorRegisteredElements.has(imageRow)) return;
cnetOpenposeEditorRegisteredElements.add(imageRow);
const generatedImageGroup = imageRow.querySelector('.cnet-generated-image-group');
const editButton = generatedImageGroup.querySelector('.cnet-edit-pose');
const modalContent = generatedImageGroup.querySelector('.cnet-modal-content');
modalContent.classList.add('alert');
modalContent.innerHTML = `
<div>
<p>
OpenPose editor not found. Please make sure you have an OpenPose editor available on <code>/openpose_editor_index</code>. To hide the edit button, check "Disable openpose edit" in Settings.<br>
<br>
The following extension(s) provide integration with ControlNet:
</p>
<ul>
<li>
<a href="https://github.com/huchenlei/sd-webui-openpose-editor">huchenlei/sd-webui-openpose-editor</a>
</li>
</ul>
</div>
`;
editButton.innerHTML = '<del>' + editButton.innerHTML + '</del>';
});
}
checkEditorAvailable().then(editorURL => {
onUiUpdate(() => {
if (editorURL)
loadOpenposeEditor(editorURL);
else
loadPlaceHolder();
});
});
})(); |