From 715e2ce6fe7db5dd87349d05c429458c5634de59 Mon Sep 17 00:00:00 2001 From: Abdullah Alfaraj Date: Thu, 17 Aug 2023 13:14:56 +0300 Subject: [PATCH] refactoring the main tab --- enum.js | 5 - index.html | 1759 +++-------------- index.js | 1158 +---------- psapi.js | 148 +- sdapi_py_re.js | 113 +- selection.js | 26 +- typescripts/after_detailer/after_detailer.tsx | 81 +- typescripts/controlnet/ControlNetTab.tsx | 145 +- typescripts/controlnet/ControlNetUnit.tsx | 42 +- typescripts/controlnet/entry.ts | 44 +- typescripts/controlnet/main.tsx | 52 +- typescripts/controlnet/store.ts | 46 +- typescripts/entry.ts | 22 +- typescripts/extra_page/extra_page.tsx | 267 +++ typescripts/history/history.tsx | 9 +- typescripts/lexical/lexical.tsx | 58 + typescripts/multiTextarea.tsx | 36 +- .../one_button_prompt/one_button_prompt.tsx | 92 +- typescripts/preset/preset.tsx | 285 +++ typescripts/preset/shared_ui_preset.ts | 120 ++ typescripts/sam/sam.tsx | 10 +- typescripts/sd_tab/sd_tab.tsx | 1260 +++++++++++- typescripts/sd_tab/util.ts | 652 ++++++ typescripts/session/generate.tsx | 136 +- typescripts/session/modes.ts | 67 +- typescripts/session/progress.ts | 15 +- typescripts/session/session.ts | 122 +- typescripts/session/session_store.ts | 65 + typescripts/settings/settings.tsx | 108 +- typescripts/stores.ts | 3 + typescripts/tool_bar/style/tool_bar.css | 4 + typescripts/tool_bar/tool_bar.tsx | 220 +++ typescripts/util/collapsible.tsx | 69 + typescripts/util/elements.tsx | 97 +- typescripts/util/oldSystem.tsx | 9 +- typescripts/util/ts/enum.ts | 12 + typescripts/util/ts/io.ts | 31 + typescripts/util/ts/layer.ts | 3 +- typescripts/util/ts/sdapi.ts | 96 + typescripts/util/ts/selection.ts | 21 +- typescripts/util/ts/ui_ts.ts | 433 ++++ typescripts/viewer/preview.tsx | 6 +- typescripts/viewer/viewer.tsx | 206 +- typescripts/viewer/viewer_util.ts | 138 ++ utility/event.js | 13 - utility/general.js | 39 +- utility/html_manip.js | 501 +---- utility/notification.js | 4 +- utility/presets/preset.js | 406 ---- utility/sdapi/python_replacement.js | 27 +- utility/session.js | 137 +- utility/tab/sd.js | 411 ---- utility/tab/settings.js | 37 +- utility/tab/share_tab.js | 17 - utility/ui.js | 282 --- 55 files changed, 4783 insertions(+), 5382 deletions(-) create mode 100644 typescripts/extra_page/extra_page.tsx create mode 100644 typescripts/lexical/lexical.tsx create mode 100644 typescripts/preset/preset.tsx create mode 100644 typescripts/preset/shared_ui_preset.ts create mode 100644 typescripts/sd_tab/util.ts create mode 100644 typescripts/session/session_store.ts create mode 100644 typescripts/stores.ts create mode 100644 typescripts/tool_bar/style/tool_bar.css create mode 100644 typescripts/tool_bar/tool_bar.tsx create mode 100644 typescripts/util/collapsible.tsx create mode 100644 typescripts/util/ts/sdapi.ts create mode 100644 typescripts/util/ts/ui_ts.ts create mode 100644 typescripts/viewer/viewer_util.ts delete mode 100644 utility/event.js delete mode 100644 utility/presets/preset.js delete mode 100644 utility/tab/sd.js delete mode 100644 utility/tab/share_tab.js delete mode 100644 utility/ui.js diff --git a/enum.js b/enum.js index 163017b..6fc4c99 100644 --- a/enum.js +++ b/enum.js @@ -37,10 +37,6 @@ const BackgroundHistoryEnum = { NoBackground: 'no_background', } -const PresetTypeEnum = { - SDPreset: 'sd_preset', - ControlNetPreset: 'controlnet_preset', -} module.exports = { clickTypeEnum, generationModeEnum, @@ -49,5 +45,4 @@ module.exports = { RequestStateEnum, BackgroundHistoryEnum, - PresetTypeEnum, } diff --git a/index.html b/index.html index fc9581b..240e8dd 100644 --- a/index.html +++ b/index.html @@ -55,7 +55,7 @@ .content { padding: 0 18px; - display: none; + /* display: none; */ overflow: hidden; } @@ -425,9 +425,6 @@ #tiNumberOfSteps { width: 50%; - } - - #tiNumberOfSteps { width: auto; } @@ -767,9 +764,7 @@
Extras
- +
Settings
@@ -903,7 +898,7 @@
- +
Explore Lexica for prompts and inspirationSelect Backend: - - Native Horde + > -->
-
- - - Resize - 2 - -
-
- - -
- No work in progress -
-
- Upscaler 1: - - - - - - -
- Upscaler 2: - - - - - - -
-
- - - Upscaler 2 visibility: - - 0 - -
-
- - - GFPGAN visibility: - - 0 - -
-
- - - CodeFormer visibility: - - 0 - -
-
- - - CodeFormer weight: - - 0 - -
+
+ +
-
- -
-
- -
- - Preset Type: - - SD Preset - ControlNet Preset - -
- - - -
- - - - - -
-
- -
-
- -
-
-
- -
- - Settings - Custom Presets - -
SD Url:
- use sharp mask + Smart Object - Live Progress Image Restore Original Prompt - Image Cfg Scale Slider Use Colab -
- - Select Extension: - - Proxy Server - Auto111 Extension - None - - -
+
- +
-
- - - - - - - - - - - -
- -
-
-
- - Progress... - - -
- - -
-
-
- - -
- - - -
-
- - - -
- - - -
- Edit Text -
- -
- - - - - - -
-
- - - -
- - - -
- -
- -
- - - - - -
-
- - -
- - - - - - - - - - -
-
- - -
- - - - - - - - - -
-
-
- -
- - - - txt2img - img2img - inpaint - outpaint - - -
- -
-
- - -
- - - - - - - - - - -
-
- - -
- -
-
- -
-
-
-
-
- -
-
- -
-
-
-
-
-
-
-
-
- Batch Size: -
-
- Batch Count: -
-
- Sampling Steps -
-
-
-
-
-
- Selection Mode: -
- - -
- - Width: - 512 - - - - Height: - 512 - - - - -
- -
- - CFG Scale: - - - - - Denoising Strength: - 0.7 - -
- - - - Mask Blur: - - - - Mask Expansion: - - - -
- - Inpainting conditioning mask - strength: - 1 - -
- -
- - Mask Content: - fill - original - latent noise - latent nothing - -
- -
- Inpaint at Full Res - Restore Faces - Hi Res Fix -
- - - Inpaint Padding: - 0 - - -
-
- -
- Seed: - - -
- - - Select Sampler: - Euler a - Euler - LMS - Heun - DPM2 - DPM2 a - DPM++ 2S a - DPM++ 2M - DPM++ SDE - DPM fast - DPM adaptive - LMS Karras - DPM2 Karras - DPM2 a Karras - DPM++ 2S a Karras - DPM++ 2M Karras - DPM++ SDE Karras - -
+
+ +
@@ -2688,49 +1259,267 @@ l32 44 -47 62 c-67 90 -253 281 -358 368 -248 208 -538 351 -802 397 -90 16 >
-
- - - - - - -
- -
+
+
+ + +
+ + + +
+
+ + + +
+ + + +
+ Edit Text +
+ +
+ + + + + + +
+
+ + + +
+ + + +
+ +
+ +
+ + + + + +
+
+ + +
+ + + + + + + + + + +
+
+ + +
+ + + + + + + + + +
+
+
diff --git a/index.js b/index.js index 807e852..0e5a43d 100644 --- a/index.js +++ b/index.js @@ -15,7 +15,6 @@ let g_online_data_url = const Jimp = require('./jimp/browser/lib/jimp.min') const Enum = require('./enum') const helper = require('./helper') -const sd_tab = require('./utility/tab/sd') const sdapi = require('./sdapi_py_re') @@ -26,8 +25,9 @@ const app = window.require('photoshop').app const constants = require('photoshop').constants const { batchPlay } = require('photoshop').action const { executeAsModal } = require('photoshop').core -const dialog_box = require('./dialog_box') +// const dialog_box = require('./dialog_box') // const {entrypoints} = require('uxp') +const { sd_tab_store } = require('./typescripts/dist/bundle') const html_manip = require('./utility/html_manip') // const export_png = require('./export_png') @@ -38,8 +38,6 @@ const sd_options = require('./utility/sdapi/options') const session = require('./utility/session') const { getSettings } = require('./utility/session') -const ui = require('./utility/ui') -const preset_util = require('./utility/presets/preset') const script_horde = require('./utility/sd_scripts/horde') const prompt_shortcut = require('./utility/sdapi/prompt_shortcut') const formats = require('uxp').storage.formats @@ -52,16 +50,15 @@ const dummy = require('./utility/dummy') const general = require('./utility/general') const thumbnail = require('./thumbnail') const note = require('./utility/notification') -const sampler_data = require('./utility/sampler') + const settings_tab = require('./utility/tab/settings') //load tabs const image_search_tab = require('./utility/tab/image_search_tab') const lexica_tab = require('./utility/tab/lexica_tab') -const share_tab = require('./utility/tab/share_tab') +// const share_tab = require('./utility/tab/share_tab') const api = require('./utility/api') -// const ultimate_sd_upscaler = require('./ultimate_sd_upscaler/dist/ultimate_sd_upscaler') -// const ultimate_sd_upscaler_script = require('./ultimate_sd_upscaler/dist/ultimate_sd_upscaler.bundle') + const { scripts, main, @@ -71,14 +68,26 @@ const { toJS, viewer, preview, - session_ts, + // session_ts, + session_store, progress, sd_tab_ts, + // sd_tab_store, sam, settings_tab_ts, one_button_prompt, enum_ts, multiPrompts, + ui_ts, + preset, + preset_util, + dialog_box, + sd_tab_util, + node_fs, + io_ts, + extra_page, + selection_ts, + stores, } = require('./typescripts/dist/bundle') const io = require('./utility/io') @@ -155,7 +164,7 @@ setLogMethod(settings_tab_ts.store.data.should_log_to_file) let g_horde_generator = new horde_native.hordeGenerator() let g_automatic_status = Enum.AutomaticStatusEnum['Offline'] -let g_models_status = false + let g_current_batch_index = 0 let g_is_laso_inapint_mode = true //REFACTOR: move to session.js @@ -182,10 +191,10 @@ async function hasSessionSelectionChanged() { return false } } -//REFACTOR: move to selection.js, add selection mode as attribute (linked to rbSelectionMode event) + async function calcWidthHeightFromSelection() { //set the width and height, hrWidth, and hrHeight using selection info and selection mode - const selection_mode = html_manip.getSelectionMode() + const selection_mode = sd_tab_store.data.selection_mode if (selection_mode === 'ratio') { //change (width and height) and (hrWidth, hrHeight) to match the ratio of selection const [width, height, hr_width, hr_height] = @@ -212,7 +221,7 @@ const eventHandler = async (event, descriptor) => { try { console.log(event, descriptor) const new_selection_info = await psapi.getSelectionInfoExe() - session_ts.store.updateProperty( + session_store.updateProperty( 'current_selection_info', new_selection_info ) @@ -317,20 +326,10 @@ document.getElementById('sp-viewer-tab').addEventListener('click', async () => { ) { g_sd_mode = 'upscale' } else { - g_sd_mode = html_manip.getMode() + g_sd_mode = sd_tab_store.data.rb_mode } }) -//REFACTOR: move to events.js -document.getElementById('sp-viewer-tab').addEventListener('click', async () => { - moveElementToAnotherTab('batchNumberUi', 'batchNumberViewerTabContainer') - await displayUpdate() -}) -//REFACTOR: move to events.js -document - .getElementById('sp-stable-diffusion-ui-tab') - .addEventListener('click', () => { - moveElementToAnotherTab('batchNumberUi', 'batchNumber-steps-container') - }) + // entrypoints.setup({ // panels:{ @@ -403,20 +402,6 @@ function getCommentedString() { console.log('getCommentedString: ', result) } -//REFACTOR: move to helpers.js -function tempDisableElement(element, time) { - element.classList.add('disableBtn') - element.disabled = true - // element.style.opacity = '0.65' - // element.style.cursor = 'not-allowed' - setTimeout(function () { - element.disabled = false - element.classList.remove('disableBtn') - // element.style.opacity = '1.0' - // element.style.cursor = 'default' - }, time) -} - //REFACTOR: move to the notfication.js async function displayNotification(automatic_status) { if (automatic_status === Enum.AutomaticStatusEnum['RunningWithApi']) { @@ -445,12 +430,12 @@ async function checkAutoStatus() { if (heartbeat) { html_manip.setProxyServerStatus('connected', 'disconnected') - session_ts.store.data.auto_photoshop_sd_extension_status = true + session_store.data.auto_photoshop_sd_extension_status = true } else { html_manip.setProxyServerStatus('disconnected', 'connected') g_automatic_status = Enum.AutomaticStatusEnum['AutoPhotoshopSDExtensionMissing'] - session_ts.store.data.auto_photoshop_sd_extension_status = false + session_store.data.auto_photoshop_sd_extension_status = false } // html_manip.setProxyServerStatus('connected','disconnected') } else { @@ -474,173 +459,6 @@ async function checkAutoStatus() { return g_automatic_status } -//REFACTOR: move to ui.js -async function refreshUI() { - try { - const b_proxy_server_status = await updateVersionUI() - if (b_proxy_server_status) { - html_manip.setProxyServerStatus('connected', 'disconnected') - // g_automatic_status = Enum.AutomaticStatusEnum['RunningWithApi'] - } else { - html_manip.setProxyServerStatus('disconnected', 'connected') - } - - g_automatic_status = await checkAutoStatus() - await displayNotification(g_automatic_status) - - const bSamplersStatus = await initSamplers() - - g_models_status = await refreshModels() - await refreshExtraUpscalers() - - await sdapi.setInpaintMaskWeight(1.0) //set the inpaint conditional mask to 1 when the on plugin start - - //get the latest options - - await g_sd_options_obj.getOptions() - //get the selected model - const current_model_title = g_sd_options_obj.getCurrentModel() - //update the ui with that model title - const current_model_hash = - html_manip.getModelHashByTitle(current_model_title) - html_manip.autoFillInModel(current_model_hash) - - //fetch the inpaint mask weight from sd webui and update the slider with it. - const inpainting_mask_weight = - await g_sd_options_obj.getInpaintingMaskWeight() - console.log('inpainting_mask_weight: ', inpainting_mask_weight) - html_manip.autoFillInInpaintMaskWeight(inpainting_mask_weight) - - //init ControlNet Tab - - g_hi_res_upscaler_models = await sd_tab.requestGetHiResUpscalers() - - g_controlnet_max_models = await control_net.requestControlNetMaxUnits() - await control_net.initializeControlNetTab(g_controlnet_max_models) - await main.populateVAE() - } catch (e) { - console.warn(e) - } -} -//REFACTOR: move to generation_settings.js -async function refreshModels() { - let b_result = false - try { - g_models = await sdapi.requestGetModels() - if (g_models.length > 0) { - b_result = true - } - - // const models_menu_element = document.getElementById('mModelsMenu') - // models_menu_element.value = "" - document.getElementById('mModelsMenu').innerHTML = '' - - for (let model of g_models) { - // console.log(model.title)//Log - const menu_item_element = document.createElement('sp-menu-item') - menu_item_element.className = 'mModelMenuItem' - menu_item_element.innerHTML = model.title - menu_item_element.dataset.model_hash = model.hash - menu_item_element.dataset.model_title = model.title - document - .getElementById('mModelsMenu') - .appendChild(menu_item_element) - } - } catch (e) { - b_result = false - console.warn(e) - } - return b_result -} -//REFACTOR: move to generation_settings.js -async function refreshExtraUpscalers() { - try { - //cycle through hrModelsMenuClass and reset innerHTML - var hrModelsMenuClass = document.getElementsByClassName( - 'hrExtrasUpscaleModelsMenuClass' - ) - for (let i = 0; i < hrModelsMenuClass.length; i++) { - hrModelsMenuClass[i].innerHTML = '' - } - g_extra_upscalers = await sdapi.requestGetUpscalers() - - for (let model of g_extra_upscalers) { - var hrModelsMenuClass = document.getElementsByClassName( - 'hrExtrasUpscaleModelsMenuClass' - ) - for (let i = 0; i < hrModelsMenuClass.length; i++) { - const menu_item_element = document.createElement('sp-menu-item') - menu_item_element.className = 'hrExtrasUpscaleModelsMenuItem' - menu_item_element.innerHTML = model.name - hrModelsMenuClass[i].appendChild(menu_item_element) - // console.log(model + ' added to ' + hrModelsMenuClass[i].id)//Log - } - } - } catch (e) { - console.warn(e) - } -} - -//REFACTOR: move to ui.js -async function updateVersionUI() { - let bStatus = false - try { - version = await sdapi.getVersionRequest() - document.getElementById('lVersionNumber').textContent = version - if (version !== 'v0.0.0') { - bStatus = true - } - } catch (e) { - console.warn(e) - document.getElementById('lVersionNumber').textContent = 'v0.0.0' - bStatus = false - } - return bStatus -} -//REFACTOR: move to generation_settings.js -async function initSamplers() { - let bStatus = false - try { - let sampler_group = document.getElementById('sampler_group') - sampler_group.innerHTML = '' - - let samplers = await sdapi.requestGetSamplers() - if (!samplers) { - //if we failed to get the sampler list from auto1111, use the list stored in sampler.js - - samplers = sampler_data.samplers - } - - for (let sampler of samplers) { - // console.log(sampler)//Log - // sampler.name - // Euler - const rbSampler = document.createElement('sp-radio') - - rbSampler.innerHTML = sampler.name - rbSampler.setAttribute('class', 'rbSampler') - rbSampler.setAttribute('value', sampler.name) - - sampler_group.appendChild(rbSampler) - //add click event on radio button for Sampler radio button, so that when a button is clicked it change g_sd_sampler globally - - //we could delete the click() event - rbSampler.addEventListener('click', (evt) => { - g_sd_sampler = evt.target.value - console.log(`You clicked: ${g_sd_sampler}`) - }) - } - document - .getElementsByClassName('rbSampler')[0] - .setAttribute('checked', '') - if (samplers.length > 0) { - bStatus = true - } - } catch (e) { - console.warn(e) - } - return bStatus -} //REFACTOR: move to helper.js function promptShortcutExample() { let prompt_shortcut_example = { @@ -667,11 +485,10 @@ let g_image_path_to_layer = {} let g_init_images_dir = './server/python_server/init_images' //REFACTOR: move to generationSettings.js gCurrentImagePath = '' -//REFACTOR: move to generationSettings.js -let g_init_image_name = '' + // let g_init_mask_layer; //REFACTOR: move to generationSettings.js -let g_init_image_mask_name = '' + // let g_mask_related_layers = {} // let g_init_image_related_layers = {} //REFACTOR: move to generationSettings.js, Note: numberOfImages deprecated global variable @@ -685,8 +502,7 @@ let g_sd_mode_last = g_sd_mode let g_sd_sampler = 'Euler a' //REFACTOR: move to generationSettings.js let g_denoising_strength = 0.7 -//REFACTOR: move to generationSettings.js -let g_use_mask_image = false + let g_models = [] // let g_models_horde = [] let g_model_title = '' @@ -705,7 +521,7 @@ let h_denoising_strength = 0.7 //REFACTOR: move to generationSettings.js let g_metadatas = [] -let g_last_seed = '-1' + //REFACTOR: move to generationSettings.js let g_can_request_progress = true let g_saved_active_layers = [] @@ -726,38 +542,12 @@ let g_sd_options_obj = new sd_options.SdOptions() g_sd_options_obj.getOptions() -// let g_width_slider = new ui.UIElement() -// g_width_slider.getValue = html_manip.getWidth -// ui_settings.uiElements.push = -let g_old_slider_width = 512 -let g_old_slider_height = 512 - -let g_hi_res_upscaler_models let g_controlnet_max_models -;(async function () { - g_hi_res_upscaler_models = await sd_tab.requestGetHiResUpscalers() - - g_controlnet_max_models = await control_net.requestControlNetMaxUnits() - - for (let model of g_hi_res_upscaler_models) { - //update the hi res upscaler models menu - let hrModelsMenuClass = - document.getElementsByClassName('hrModelsMenuClass') - for (let i = 0; i < hrModelsMenuClass.length; i++) { - const menu_item_element = document.createElement('sp-menu-item') - menu_item_element.className = 'hrModelsMenuItem' - menu_item_element.innerHTML = model - hrModelsMenuClass[i].appendChild(menu_item_element) - // console.log(model + ' added to ' + hrModelsMenuClass[i].id)//Log - } - } -})() let g_generation_session = new session.GenerationSession(0) //session manager g_generation_session.deactivate() //session starte as inactive -let g_ui = new ui.UI() -let g_ui_settings_object = ui.getUISettingsObject() +let g_ui_settings_object = ui_ts.getUISettingsObject() let g_batch_count_interrupt_status = false const requestState = { Generate: 'generate', @@ -784,53 +574,6 @@ g_generation_session.mode = generationMode['Txt2Img'] //********** End: global variables */ -//***********Start: init function calls */ -//REFACTOR: keep in index.js -async function initPlugin() { - //*) load plugin settings - //*) load horde settings - //*) - //*) initialize the samplers - //*) - await settings_tab.loadSettings() - await horde_native.HordeSettings.loadSettings() - const bSamplersStatus = await initSamplers() //initialize the sampler - await sdapi.setInpaintMaskWeight(1.0) //set the inpaint conditional mask to 1 when the on plugin start - await refreshUI() - await displayUpdate() - // promptShortcutExample() - await loadPromptShortcut() - await refreshPromptMenue() -} -initPlugin() -// refreshModels() // get the models when the plugin loads -// initSamplers() -// updateVersionUI() -// refreshUI() -// displayUpdate() -// loadPromptShortcut() -// // promptShortcutExample() - -//***********End: init function calls */ - -//add click event on radio button mode, so that when a button is clicked it change g_sd_mode globally -//REFACTOR: move to events.js -rbModeElements = document.getElementsByClassName('rbMode') -for (let rbModeElement of rbModeElements) { - rbModeElement.addEventListener('click', async (evt) => { - try { - g_sd_mode = evt.target.value - scripts.script_store.setMode(g_sd_mode) - sd_tab_ts.store.updateProperty('mode', g_sd_mode) - // console.log(`You clicked: ${g_sd_mode}`) - await displayUpdate() - await postModeSelection() // do things after selection - } catch (e) { - console.warn(e) - } - }) -} - //swaps g_sd_mode when clicking on extras tab and swaps it back to previous value when clicking on main tab //REFACTOR: move to events.js document @@ -839,9 +582,9 @@ document try { // g_sd_mode_last = g_sd_mode g_sd_mode = 'upscale' - sd_tab_ts.store.updateProperty('mode', 'upscale') + sd_tab_store.updateProperty('mode', 'upscale') console.log(`You clicked: ${g_sd_mode}`) - await displayUpdate() + await postModeSelection() // do things after selection } catch (e) { console.warn(e) @@ -853,10 +596,10 @@ document .addEventListener('click', async (evt) => { try { // g_sd_mode = g_sd_mode_last - g_sd_mode = html_manip.getMode() - sd_tab_ts.store.updateProperty('mode', html_manip.getMode()) + g_sd_mode = sd_tab_store.data.rb_mode + sd_tab_store.updateProperty('mode', sd_tab_store.data.rb_mode) console.log(`mode restored to: ${g_sd_mode}`) - await displayUpdate() + await postModeSelection() // do things after selection } catch (e) { console.warn(e) @@ -920,44 +663,7 @@ async function postModeSelection() { console.warn(e) } } -rbMaskContentElements = document.getElementsByClassName('rbMaskContent') -//REFACTOR: move to events.js -for (let rbMaskContentElement of rbMaskContentElements) { - rbMaskContentElement.addEventListener('click', async (evt) => { - // g_inpainting_fill = evt.target.value - // console.log(`You clicked: ${g_inpainting_fill}`) - }) -} -btnSquareClass = document.getElementsByClassName('btnSquare') -//REFACTOR: move to events.js -for (let btnSquareButton of btnSquareClass) { - btnSquareButton.addEventListener('click', async (evt) => { - // document.activeElement.blur() - setTimeout(() => { - try { - evt.target.blur() - } catch (e) { - console.warn(e) - } - }, 500) - }) -} - -btnRefreshModelsClass = document.getElementsByClassName('btnRefreshModels') -//REFACTOR: move to events.js -for (let btnRefreshModel of btnRefreshModelsClass) { - btnRefreshModel.addEventListener('click', async (evt) => { - // document.activeElement.blur() - setTimeout(() => { - try { - evt.target.blur() - } catch (e) { - console.warn(e) - } - }, 500) - }) -} //REFACTOR: move to events.js document.addEventListener('mouseenter', async (event) => { try { @@ -992,206 +698,7 @@ document.addEventListener('mouseenter', async (event) => { console.warn(e) } }) -////add tips to element when mouse hover on an element -// function getToolTipElement(){ -// const tool_tip = document.getElementById("tool_tip") -// return tool_tip -// } -// function moveTip(x,y){ -// var tool_tip = document.getElementById("tool_tip") -// tool_tip.style.position = 'absolute'; -// tool_tip.style.left = x; -// tool_tip.style.top = y; -// } -// document.getElementById('rbOutpaintMode').addEventListener("mouseover",(e)=>{ - -// console.log("e.shiftKey:",e.shiftKey) - -// if(e.shiftKey) -// { -// const rect = e.target.getBoundingClientRect() -// const tool_tip = getToolTipElement() -// setTimeout(()=>{ -// tool_tip.style.display = "none" -// },5000) -// tool_tip.style.display = "inline-block" - -// tool_tip.style["z-index"] = 100; -// console.log("Use this mode when you want to fill empty areas of the canvas") -// // var x = e.pageX; -// // var y = e.pageY; -// console.log("(e.pageX,e.pageY): ",(e.pageX,e.pageY)) -// const tip_x = e.pageX - (tool_tip.offsetWidth/2) -// // const tip_y = e.pageY + - tool_tip.offsetHeight -// const tip_y = rect.top + - tool_tip.offsetHeight - -// moveTip(tip_x,tip_y) -// } -// else{// rlease the shift key -// console.log("tip will disappear in 1 second") -// } - -// }); - -// document.getElementById('rbOutpaintMode').addEventListener("mouseout",(e)=>{ - -// console.log("e.shiftKey:",e.shiftKey) - -// console.log("no tip, tip will disappear in 1 second") -// // getToolTipElement().style.display = "none" - -// }); - -// show the interface that need to be shown and hide the interface that need to be hidden -//REFACTOR: move to ui.js -async function displayUpdate() { - try { - sd_tab.displayImageCfgScaleSlider(g_sd_mode) - if (g_sd_mode == 'txt2img') { - document.getElementById('slDenoisingStrength').style.display = - 'none' // hide denoising strength slider - // document.getElementById("image_viewer").style.display = 'none' // hide images - document.getElementById('init_image_container').style.display = - 'none' // hide init image - document.getElementById('init_image_mask_container').style.display = - 'none' // hide init mask - document.getElementById('slInpainting_fill').style.display = 'none' // hide inpainting fill mode - document.getElementById('chInpaintFullRes').style.display = 'none' - - document.getElementById('slInpaintingMaskWeight').style.display = - 'none' // hide inpainting conditional mask weight - - document.getElementById('chHiResFixs').style.display = 'flex' - if (html_manip.getHiResFixs()) { - document.getElementById('HiResDiv').style.display = 'block' - } - - document.getElementById('slMaskExpansion').style.display = 'none' - - document.getElementById('slInpaintPadding').style.display = 'none' - document.getElementById('slMaskBlur').style.display = 'none' - // document.getElementById('slImageCfgScale').style.display = 'none' - // document.getElementById('btnSnapAndFill').style.display = 'none'//"none" will misaligned the table // hide snap and fill button - } - - if (g_sd_mode == 'img2img') { - document.getElementById('slDenoisingStrength').style.display = - 'block' // show denoising strength - document.getElementById('slMaskExpansion').style.display = 'none' - // document.getElementById("image_viewer").style.display = 'block' - document.getElementById('init_image_container').style.display = - 'block' // hide init image - - document.getElementById('init_image_mask_container').style.display = - 'none' // hide mask - document.getElementById('slInpainting_fill').style.display = 'none' // hide inpainting fill mode - // document.getElementById('btnSnapAndFill').style.display = 'inline-flex' // hide snap and fill button mode - document.getElementById('HiResDiv').style.display = 'none' - document.getElementById('chInpaintFullRes').style.display = 'none' - document.getElementById('slInpaintPadding').style.display = 'none' - document.getElementById('slMaskBlur').style.display = 'none' - document.getElementById('chHiResFixs').style.display = 'none' - document.getElementById('slInpaintingMaskWeight').style.display = - 'block' // hide inpainting conditional mask weight - - // document.getElementById('slImageCfgScale').style.display = 'block' - } - - if (g_sd_mode == 'inpaint' || g_sd_mode == 'outpaint') { - ///fix the misalignment problem in the ui (init image is not aligned with init mask when switching from img2img to inpaint ). note: code needs refactoring - // document.getElementById('btnSnapAndFill').style.display = 'none'//"none" will misaligned the table // hide snap and fill button - document.getElementById('tableInitImageContainer').style.display = - 'none' // hide the table - document.getElementById('slMaskExpansion').style.display = 'block' - setTimeout(() => { - try { - document.getElementById( - 'tableInitImageContainer' - ).style.display = 'table' // show the table after some time so it gets rendered. - } catch (e) { - console.warn(e) - } - }, 100) - - document.getElementById('slDenoisingStrength').style.display = - 'block' - document.getElementById('init_image_mask_container').style.display = - 'block' - document.getElementById('slInpainting_fill').style.display = 'block' - document.getElementById('init_image_container').style.display = - 'block' // hide init image - document.getElementById('slInpaintingMaskWeight').style.display = - 'block' // hide inpainting conditional mask weight - - document.getElementById('HiResDiv').style.display = 'none' - document.getElementById('chInpaintFullRes').style.display = - 'inline-flex' - if (document.getElementById('chInpaintFullRes').checked) { - document.getElementById('slInpaintPadding').style.display = - 'block' - } else { - document.getElementById('slInpaintPadding').style.display = - 'none' - } - document.getElementById('slMaskBlur').style.display = 'block' - document.getElementById('chHiResFixs').style.display = 'none' - - // document.getElementById('btnInitOutpaint').style.display = 'inline-flex' - // document.getElementById('btnInitInpaint').style.display = 'inline-flex' - // document.getElementById('btnInitOutpaint').style.display = 'none' - // document.getElementById('btnInitInpaint').style.display = 'none' - } else { - //txt2img or img2img - // document.getElementById('btnInitOutpaint').style.display = 'none' - // document.getElementById('btnInitInpaint').style.display = 'none' - } - - if (g_generation_session.isActive()) { - //Note: remove the "or" operation after refactoring the code - //if the session is active - - if (g_generation_session.mode !== g_sd_mode) { - //if a generation session is active but we changed mode. the generate button will reflect that - //Note: add this code to the UI class - const generate_btns = Array.from( - document.getElementsByClassName('btnGenerateClass') - ) - generate_btns.forEach((element) => { - const selected_mode = - getCurrentGenerationModeByValue(g_sd_mode) - element.textContent = `Generate ${selected_mode}` - }) - } else { - //1) and the session is active - //2) is the same generation mode - - if (!(await hasSessionSelectionChanged())) { - //3a) and the selection hasn't change - - const generate_btns = Array.from( - document.getElementsByClassName('btnGenerateClass') - ) - - // const selected_mode = - // getCurrentGenerationModeByValue(g_sd_mode) - const generation_mode = g_generation_session.mode - const generation_name = - getCurrentGenerationModeByValue(generation_mode) - generate_btns.forEach((element) => { - element.textContent = `Generate More ${generation_name}` - }) - } else { - //3b) selection has change - } - } - } else { - //session is not active - } - } catch (e) { - console.warn(e) - } -} // function showLayerNames () { // const app = window.require('photoshop').app // const allLayers = app.activeDocument.layers @@ -1283,44 +790,6 @@ function sliderToResolution(sliderValue) { return sliderValue * 64 } -//REFACTOR: move to events.js -document.querySelector('#hrHeight').addEventListener('input', (evt) => { - hHeight = sliderToResolution(evt.target.value) - document.querySelector('#hHeight').textContent = hHeight -}) -//REFACTOR: move to events.js -document.querySelector('#hrWidth').addEventListener('input', (evt) => { - hWidth = sliderToResolution(evt.target.value) - document.querySelector('#hWidth').textContent = hWidth -}) - -//REFACTOR: move to events.js -document.querySelector('#slInpaintPadding').addEventListener('input', (evt) => { - padding = evt.target.value * 4 - document.querySelector('#lInpaintPadding').textContent = padding -}) - -//REFACTOR: move to events.js -document.getElementById('btnRandomSeed').addEventListener('click', async () => { - document.querySelector('#tiSeed').value = '-1' -}) -//REFACTOR: move to events.js -document.getElementById('btnLastSeed').addEventListener('click', async () => { - try { - // console.log('click on Last seed') - let seed = '-1' - - if (g_last_seed >= 0) { - seed = g_last_seed.toString() //make sure the seed is a string - } - - // console.log('seed:', seed) - document.querySelector('#tiSeed').value = seed - } catch (e) { - console.warn(e) - } -}) - //REFACTOR: move to psapi.js //store active layers only if they are not stored. async function storeActiveLayers() { @@ -1408,62 +877,6 @@ function updateMetadata(new_metadata) { return metadatas } -//REFACTOR: move to generation_settings.js -async function getExtraSettings() { - let payload = {} - try { - const html_manip = require('./utility/html_manip') - const upscaling_resize = html_manip.getUpscaleSize() - const gfpgan_visibility = html_manip.getGFPGANVisibility() - const codeformer_visibility = html_manip.getCodeFormerVisibility() - const codeformer_weight = html_manip.getCodeFormerWeight() - const selection_info = await psapi.getSelectionInfoExe() - const width = selection_info.width * upscaling_resize - const height = selection_info.height * upscaling_resize - //resize_mode = 0 means "resize to upscaling_resize" - //resize_mode = 1 means "resize to width and height" - payload['resize_mode'] = 0 - payload['show_extras_results'] = 0 - payload['gfpgan_visibility'] = gfpgan_visibility - payload['codeformer_visibility'] = codeformer_visibility - payload['codeformer_weight'] = codeformer_weight - payload['upscaling_resize'] = upscaling_resize - payload['upscaling_resize_w'] = width - payload['upscaling_resize_h'] = height - payload['upscaling_crop'] = true - const upscaler1 = document.querySelector('#hrModelsMenuUpscale1').value - payload['upscaler_1'] = upscaler1 === undefined ? 'None' : upscaler1 - const upscaler2 = document.querySelector('#hrModelsMenuUpscale2').value - payload['upscaler_2'] = upscaler2 === undefined ? 'None' : upscaler2 - const extras_upscaler_2_visibility = html_manip.getUpscaler2Visibility() - payload['extras_upscaler_2_visibility'] = extras_upscaler_2_visibility - payload['upscale_first'] = false - const uniqueDocumentId = await getUniqueDocumentId() - payload['uniqueDocumentId'] = uniqueDocumentId - - // const layer = await app.activeDocument.activeLayers[0] - const layer = await app.activeDocument.activeLayers[0] - const old_name = layer.name - - // image_name = await app.activeDocument.activeLayers[0].name - - //convert layer name to a file name - let image_name = psapi.layerNameToFileName( - old_name, - layer.id, - random_session_id - ) - image_name = `${image_name}.png` - - const base64_image = g_generation_session.activeBase64InitImage - - payload['image'] = base64_image - } catch (e) { - console.error(e) - } - return payload -} - //REFACTOR: move to selection.js async function hasSelectionChanged(new_selection, old_selection) { if ( @@ -1478,51 +891,6 @@ async function hasSelectionChanged(new_selection, old_selection) { } } -document - .getElementById('btnRefreshModels') - .addEventListener('click', async (e) => { - await refreshUI() - await sd_tab.refreshSDTab() - tempDisableElement(e.target, 3000) - }) -//REFACTOR: move to events.js -document.querySelector('#mModelsMenu').addEventListener('change', (evt) => { - const model_index = evt.target.selectedIndex - console.log(`Selected item: ${evt.target.selectedIndex}`) - let model = g_models[0] - if (model_index < g_models.length) { - model = g_models[model_index] - } - // g_model_name = `${model.model_name}.ckpt` - g_model_title = model.title - console.log('g_model_title: ', g_model_title) - sdapi.requestSwapModel(g_model_title) -}) -//REFACTOR: move to events.js -document.querySelectorAll('.btnLayerToSelection').forEach((el) => { - el.addEventListener('click', async () => { - try { - const isSelectionAreaValid = - await psapi.checkIfSelectionAreaIsActive() - if (isSelectionAreaValid) { - const validSelection = isSelectionAreaValid - await psapi.layerToSelection(validSelection) - } else { - await psapi.promptForMarqueeTool() - } - } catch (e) { - console.warn(e) - } - }) -}) - -//REFACTOR: move to psapi.js -function moveElementToAnotherTab(elementId, newParentId) { - const element = document.getElementById(elementId) - document.getElementById(newParentId).appendChild(element) -} - -// moveElementToAnotherTab("batchNumberUi","batchNumberViewerTabContainer") //REFACTOR: move to ui.js function updateProgressBarsHtml(new_value) { document.querySelectorAll('.pProgressBars').forEach((el) => { @@ -1537,288 +905,7 @@ function updateProgressBarsHtml(new_value) { }) // document.querySelector('#pProgressBar').value } -//REFACTOR: move to ui.js -async function updateProgressImage(progress_base64) { - try { - await executeAsModal(async (context) => { - const history_id = await context.hostControl.suspendHistory({ - documentID: app.activeDocument.id, //TODO: change this to the session document id - name: 'Progress Image', - }) - await g_generation_session.deleteProgressLayer() // delete the old progress layer - //update the progress image - const selection_info = await g_generation_session.selectionInfo - const b_exsit = layer_util.Layer.doesLayerExist( - g_generation_session.progress_layer - ) - if (!b_exsit) { - const layer = await io.IO.base64ToLayer( - progress_base64, - 'temp_progress_image.png', - selection_info.left, - selection_info.top, - selection_info.width, - selection_info.height - ) - g_generation_session.progress_layer = layer // sotre the new progress layer// TODO: make sure you delete the progress layer when the geneeration request end - } else { - // if ,somehow, the layer still exsit - await layer_util.deleteLayers([ - g_generation_session.progress_layer, - ]) // delete the old progress layer - } - await context.hostControl.resumeHistory(history_id) - }) - } catch (e) { - console.warn(e) - } -} -//REFACTOR: move to ui.js -async function progressRecursive() { - try { - let json = await sdapi.requestProgress() - // document.querySelector('#pProgressBar').value = json.progress * 100 - const progress_value = json.progress * 100 - if (g_generation_session.sudo_timer_id) { - //for sudo timer update - //for controlnet only: disable the sudo timer when the real timer start - // - if (progress_value > 1) { - //disable the sudo timer at the end of the generation - g_generation_session.sudo_timer_id = clearInterval( - g_generation_session.sudo_timer_id - ) - } - } else { - //for normal progress bar - - html_manip.updateProgressBarsHtml(progress_value) - } - - if ( - json?.current_image && - g_generation_session.request_status === - Enum.RequestStateEnum['Generating'] - ) { - const base64_url = general.base64ToBase64Url(json.current_image) - preview.store.updateProperty('image', json.current_image) - - const progress_image_html = document.getElementById('progressImage') - const container_width = document.querySelector( - '#divProgressImageViewerContainer' - ).offsetWidth - //*) find the parent container width - //*) set the width of the image to auto - //*) scale to closest while keeping the ratio, the hieght should not be larger than the width of the container - - // height: 10000px; - // width: auto; - // background-size: contain; - - // progress_image_html.style.backgroundSize = 'contain' - // progress_image_html.style.height = '10000px' - - // document.getElementById( - // 'divProgressImageViewerContainer' - // ).style.backgroundImage = `url('${base64_url}')` - - html_manip.setProgressImageSrc(base64_url) - - // if (progress_image_html.style.width !== 'auto') { - // progress_image_html.style.width = 'auto' - // } - // if ((progress_image_html.style.height = 'auto' !== 'auto')) { - // progress_image_html.style.height = 'auto' - // } - - // progress_image_html = new_height - // progress_image_html.style.width = progress_image_html.naturalWidth - // progress_image_html.style.height = progress_image_html.naturalHeight - - if ( - g_generation_session.last_settings.batch_size === 1 && - settings_tab.getUseLiveProgressImage() - ) { - //only update the canvas if the number of images are one - //don't update the canvas with multiple images. - await updateProgressImage(json.current_image) - } - } - if (g_generation_session.isActive() && g_can_request_progress == true) { - //refactor this code - setTimeout(async () => { - await progressRecursive() - }, 1000) - } - } catch (e) { - console.warn(e) - if ( - g_generation_session.isActive() && - g_can_request_progress === true - ) { - setTimeout(async () => { - await progressRecursive() - }, 1000) - } - } -} -//REFACTOR: move to ui.js -function changeImage() { - let img = document.getElementById('img1') - img.src = 'https://source.unsplash.com/random' -} - -// document.getElementById('btnChangeImage').addEventListener('click', changeImage) -//REFACTOR: move to psapi.js -async function imageToSmartObject() { - const { batchPlay } = require('photoshop').action - const { executeAsModal } = require('photoshop').core - - try { - // const file = await fs.getFileForOpening() - // token = await fs.getEntryForPersistentToken(file); - // const entry = await fs.getEntryForPersistentToken(token); - // const session_token = await fs.createSessionToken(entry); - // // let token = await fs.createSessionToken(entry) - await executeAsModal( - async () => { - console.log('imageToSmartObject():') - const storage = require('uxp').storage - const fs = storage.localFileSystem - let pluginFolder = await fs.getPluginFolder() - let img = await pluginFolder.getEntry( - 'output- 1672730735.1670313.png' - ) - const result = await batchPlay( - [ - { - _obj: 'placeEvent', - ID: 95, - null: { - _path: img, - _kind: 'local', - }, - freeTransformCenterState: { - _enum: 'quadCenterState', - _value: 'QCSAverage', - }, - offset: { - _obj: 'offset', - horizontal: { - _unit: 'pixelsUnit', - _value: 0, - }, - vertical: { - _unit: 'pixelsUnit', - _value: 0, - }, - }, - replaceLayer: { - _obj: 'placeEvent', - from: { - _ref: 'layer', - _id: 56, - }, - to: { - _ref: 'layer', - _id: 70, - }, - }, - _options: { - dialogOptions: 'dontDisplay', - }, - }, - ], - { - synchronousExecution: true, - modalBehavior: 'execute', - } - ) - }, - { - commandName: 'Create Label', - } - ) - } catch (e) { - console.log('imageToSmartObject() => error: ') - console.warn(e) - } -} - -// document.getElementById('btnNewLayer').addEventListener('click', imageToSmartObject ) -//REFACTOR: move to psapi.js -async function placeEmbedded(image_name, dir_entery) { - //silent importer - - try { - // console.log('placeEmbedded(): image_path: ', image_path) - - const formats = require('uxp').storage.formats - const storage = require('uxp').storage - const fs = storage.localFileSystem - // const names = image_path.split('/') - // const length = names.length - // const image_name = names[length - 1] - // const project_name = names[length - 2] - let image_dir = dir_entery - // const image_dir = `./server/python_server/output/${project_name}` - // image_path = "output/f027258e-71b8-430a-9396-0a19425f2b44/output- 1674323725.126322.png" - - // let img_dir = await .getEntry(image_dir) - // const file = await img_dir.createFile('output- 1674298902.0571606.png', {overwrite: true}); - - const file = await image_dir.createFile(image_name, { overwrite: true }) - - const img = await file.read({ format: formats.binary }) - const token = await storage.localFileSystem.createSessionToken(file) - let place_event_result - await executeAsModal(async () => { - const result = await batchPlay( - [ - { - _obj: 'placeEvent', - ID: 6, - null: { - _path: token, - _kind: 'local', - }, - freeTransformCenterState: { - _enum: 'quadCenterState', - _value: 'QCSAverage', - }, - offset: { - _obj: 'offset', - horizontal: { - _unit: 'pixelsUnit', - _value: 0, - }, - vertical: { - _unit: 'pixelsUnit', - _value: 0, - }, - }, - _isCommand: true, - _options: { - dialogOptions: 'dontDisplay', - }, - }, - ], - { - synchronousExecution: true, - modalBehavior: 'execute', - } - ) - console.log('placeEmbedd batchPlay result: ', result) - - place_event_result = result[0] - }) - - return place_event_result - } catch (e) { - console.warn(e) - } -} //REFACTOR: move to psapi.js function _base64ToArrayBuffer(base64) { var binary_string = window.atob(base64) @@ -1955,8 +1042,6 @@ async function placeImageB64ToLayer(image_path, entery) { //silent importer try { - console.log('placeEmbedded(): image_path: ', image_path) - const formats = require('uxp').storage.formats const storage = require('uxp').storage const fs = storage.localFileSystem @@ -2025,8 +1110,6 @@ async function placeImageB64ToLayer(image_path, entery) { } } -// document.getElementById('btnImageFileToLayer').addEventListener('click', placeEmbedded) - // open an image in the plugin folder as new document //REFACTOR: move to document.js async function openImageAction() { @@ -2121,7 +1204,7 @@ async function silentImagesToLayersExe_old(images_info) { // if (base64_images) { // placeEventResult = await base64ToFile(base64_images) //silent import into the document // } else { - // placeEventResult = await placeEmbedded(image_path) //silent import into the document + // } placeEventResult = await base64ToFile(image_info.base64) //silent import into the document @@ -2208,7 +1291,7 @@ async function silentImagesToLayersExe(images_info) { // if (base64_images) { // placeEventResult = await base64ToFile(base64_images) //silent import into the document // } else { - // placeEventResult = await placeEmbedded(image_path) //silent import into the document + // } // imported_layer = await base64ToFile(image_info.base64) //silent import into the document const selection_info = await g_generation_session.selectionInfo @@ -2263,8 +1346,6 @@ async function silentImagesToLayersExe(images_info) { g_generation_session.isLoadingActive = false } -// document.getElementById('btnLoadImages').addEventListener('click',ImagesToLayersExe) - //stack layer to original document //REFACTOR: move to psapi.js async function stackLayers() { @@ -2302,19 +1383,6 @@ async function stackLayers() { } }) } -//REFACTOR: move to events.js -document.getElementById('collapsible').addEventListener('click', function () { - this.classList.toggle('active') - var content = this.nextElementSibling - console.log('content:', content) - if (content.style.display === 'block') { - content.style.display = 'none' - this.textContent = 'Show Samplers' - } else { - content.style.display = 'block' - this.textContent = 'Hide Samplers' - } -}) function removeInitImageFromViewer() {} function removeMaskFromViewer() {} @@ -2392,27 +1460,11 @@ async function turnMaskVisible( } } -//REFACTOR: move to document.js -async function loadPromptShortcut() { - try { - let prompt_shortcut = await sdapi.loadPromptShortcut() - if (!prompt_shortcut || prompt_shortcut === {}) { - prompt_shortcut = promptShortcutExample() - } - - // var JSONInPrettyFormat = JSON.stringify(prompt_shortcut, undefined, 4); - // document.getElementById('taPromptShortcut').value = JSONInPrettyFormat - html_manip.setPromptShortcut(prompt_shortcut) // fill the prompt shortcut textarea - await refreshPromptMenue() //refresh the prompt menue - } catch (e) { - console.warn(`loadPromptShortcut warning: ${e}`) - } -} //REFACTOR: move to events.js document .getElementById('btnLoadPromptShortcut') .addEventListener('click', async function () { - await loadPromptShortcut() + await sd_tab_util.loadPromptShortcut() }) //REFACTOR: move to events.js document @@ -2436,7 +1488,7 @@ document console.log(JSONInPrettyFormat) document.getElementById('taPromptShortcut').value = JSONInPrettyFormat - await refreshPromptMenue() + await refreshPromptMenu() } catch (e) { console.warn(`loadPromptShortcut warning: ${e}`) } @@ -2473,18 +1525,24 @@ document } }) -var chHiResFixs = document.getElementById('chHiResFixs') -var div = document.getElementById('HiResDiv') -//REFACTOR: move to events.js -chHiResFixs.addEventListener('change', function () { - if (chHiResFixs.checked) { - div.style.display = 'block' - } else { - div.style.display = 'none' +//REFACTOR: move to document.js +async function loadPromptShortcut() { + try { + let prompt_shortcut = await sdapi.loadPromptShortcut() + if (!prompt_shortcut || prompt_shortcut === {}) { + prompt_shortcut = promptShortcutExample() + } + + // var JSONInPrettyFormat = JSON.stringify(prompt_shortcut, undefined, 4); + // document.getElementById('taPromptShortcut').value = JSONInPrettyFormat + html_manip.setPromptShortcut(prompt_shortcut) // fill the prompt shortcut textarea + await refreshPromptMenu() //refresh the prompt menue + } catch (e) { + console.warn(`loadPromptShortcut warning: ${e}`) } -}) +} //REFACTOR: move to ui.js -async function refreshPromptMenue() { +async function refreshPromptMenu() { try { //get the prompt_shortcut_json //iterate over the each entery @@ -2522,7 +1580,7 @@ document document .getElementById('btnRefreshPromptShortcutMenu') .addEventListener('click', async () => { - await refreshPromptMenue() + await refreshPromptMenu() }) //REFACTOR: move to ui.js function changePromptShortcutKey(new_key) { @@ -2533,40 +1591,6 @@ function changePromptShortcutValue(new_value) { document.getElementById('ValuePromptShortcut').value = new_value } -// adding a listner here for the inpaint_mask_strengh to be able to use api calls, allowing to dynamicly change the value -// a set button could be added to the ui to reduce the number of api calls in case of a slow connection -//REFACTOR: move to events.js -document - .querySelector('#slInpaintingMaskWeight') - .addEventListener('input', async (evt) => { - const label_value = evt.target.value / 100 - document.getElementById( - 'lInpaintingMaskWeight' - ).innerHTML = `${label_value}` - // await sdapi.setInpaintMaskWeight(label_value) - }) -//REFACTOR: move to events.js -document - .querySelector('#slInpaintingMaskWeight') - .addEventListener('change', async (evt) => { - try { - const label_value = evt.target.value / 100 - document.getElementById( - 'lInpaintingMaskWeight' - ).innerHTML = `${label_value}` - await sdapi.setInpaintMaskWeight(label_value) - - // //get the inpaint mask weight from the webui sd - // await g_sd_options_obj.getOptions() - // const inpainting_mask_weight = - // await g_sd_options_obj.getInpaintingMaskWeight() - - // console.log('inpainting_mask_weight: ', inpainting_mask_weight) - // html_manip.autoFillInInpaintMaskWeight(inpainting_mask_weight) - } catch (e) { - console.warn(e) - } - }) //REFACTOR: move to document.js async function downloadIt(link, writeable_entry, image_file_name) { const image = await fetch(link) @@ -2620,34 +1644,6 @@ async function downloadItExe(link, writeable_entry, image_file_name) { return new_layer } -//REFACTOR: move to session.js or selection.js -async function activateSessionSelectionArea() { - try { - if (psapi.isSelectionValid(session_ts.store.data.selectionInfo)) { - await psapi.reSelectMarqueeExe(session_ts.store.data.selectionInfo) - await eventHandler() - } - } catch (e) { - console.warn(e) - } -} -//REFACTOR: move to events.js -document - .getElementById('btnSelectionArea') - .addEventListener('click', async () => { - // try { - // if (psapi.isSelectionValid(g_generation_session.selectionInfo)) { - // await psapi.reSelectMarqueeExe( - // g_generation_session.selectionInfo - // ) - // await eventHandler() - // } - // } catch (e) { - // console.warn(e) - // } - await activateSessionSelectionArea() - }) - //REFACTOR: move to psapi.js function base64ToSrc(base64_image) { const image_src = `data:image/png;base64, ${base64_image}` @@ -2674,13 +1670,6 @@ function getDimensions(image) { }) } -//REFACTOR: move to events.js -document.getElementById('linkWidthHeight').addEventListener('click', (evt) => { - evt.target.classList.toggle('blackChain') - const b_state = !evt.target.classList.contains('blackChain') //if doesn't has blackChain means => it's white => b_state == true - html_manip.setLinkWidthHeightState(b_state) -}) - //REFACTOR: move to events.js function switchMenu(rb) { @@ -2698,7 +1687,7 @@ function switchMenu(rb) { .getElementById(tab_page_name) .querySelector(`.${contianer_class}`) // .querySelector('.subTabOptionsContainer') - // const radio_group = document.getElementById('rgSubTab') + rb.checked = true option_container.appendChild(radio_group) }) @@ -2711,28 +1700,6 @@ function switchMenu(rb) { } } -//REFACTOR: move to ui.js -async function updateResDifferenceLabel() { - const ratio = await selection.Selection.getImageToSelectionDifference() - const arrow = ratio >= 1 ? '↑' : '↓' - let final_ratio = ratio // this ratio will always be >= 1 - if (ratio >= 1) { - // percentage = percentage >= 1 ? percentage : 1 / percentage - - // const percentage_str = `${arrow}X${percentage.toFixed(2)}` - - // console.log('scale_info_str: ', scale_info_str) - // console.log('percentage_str: ', percentage_str) - document - .getElementById('res-difference') - .classList.remove('res-decrease') - } else { - final_ratio = 1 / ratio - document.getElementById('res-difference').classList.add('res-decrease') - } - const ratio_str = `${arrow}x${final_ratio.toFixed(2)}` - document.getElementById('res-difference').innerText = ratio_str -} //REFACTOR: move to events.js document .getElementById('btnSaveHordeSettings') @@ -2831,7 +1798,7 @@ function switchMenu_new(rb) { .getElementById(tab_page_name) .querySelector(`.${contianer_class}`) // .querySelector('.subTabOptionsContainer') - // const radio_group = document.getElementById('rgSubTab') + rb.checked = true option_container.appendChild(radio_group) }) @@ -2859,13 +1826,6 @@ Array.from(document.querySelectorAll('.rbSubTab')).forEach((rb) => { switchMenu(rb) }) -document.getElementById('scrollToPrompt').addEventListener('click', () => { - document - .querySelector('#search_second_panel > div.previewContainer') - .scrollIntoView() - // document.getElementById('taPrompt').scrollIntoView() -}) - // document.getElementById('scrollToViewer').addEventListener('click', () => { // document diff --git a/psapi.js b/psapi.js index 151ca17..8c9ddd1 100644 --- a/psapi.js +++ b/psapi.js @@ -787,147 +787,6 @@ function layerNameToFileName(layer_name, layer_id, session_id) { return file_name } -async function silentSetInitImage(layer, session_id) { - try { - const html_manip = require('./utility/html_manip') - const io = require('./utility/io') - // const layer = await app.activeDocument.activeLayers[0] - const old_name = layer.name - - // image_name = await app.activeDocument.activeLayers[0].name - - //convert layer name to a file name - let image_name = layerNameToFileName(old_name, layer.id, session_id) - image_name = `${image_name}.png` - - //the width and height of the exported image - const width = html_manip.getWidth() - const height = html_manip.getHeight() - - //get the selection from the canvas as base64 png, make sure to resize to the width and height slider - const selectionInfo = g_generation_session.selectionInfo - // const base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent( - // selectionInfo, - // true, - // width, - // height - // ) - - const use_silent_mode = html_manip.getUseSilentMode() - // if (use_silent_mode) { - // base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent( - // selectionInfo, - // true, - // width, - // height - // ) - // } else { - // base64_image = await io.IO.getSelectionFromCanvasAsBase64NonSilent( - // layer, - - // image_name, - // width, - // height - // ) - // } - const base64_image = - await io.IO.getSelectionFromCanvasAsBase64Interface( - width, - height, - layer, - selectionInfo, - true, - use_silent_mode, - image_name - ) - //save base64 as file in the init_images directory - const init_entry = await getInitImagesDir() - await io.IO.base64PngToPngFile(base64_image, init_entry, image_name) - - g_init_image_name = image_name - console.log(image_name) - - const path = `${g_init_images_dir}/${image_name}` - - //store the base64 init image and also set it as the active/latest init image - g_generation_session.base64initImages[path] = base64_image - g_generation_session.activeBase64InitImage = base64_image - - const init_src = base64ToSrc(g_generation_session.activeBase64InitImage) - html_manip.setInitImageSrc(init_src) - - return (image_info = { name: image_name, base64: base64_image }) - } catch (e) { - console.error(`psapi.js silentSetInitImage error:, ${e}`) - } -} -async function silentSetInitImageMask(layer, session_id) { - try { - const html_manip = require('./utility/html_manip') - - // const layer = await app.activeDocument.activeLayers[0] - const old_name = layer.name - - image_name = layerNameToFileName(old_name, layer.id, session_id) - image_name = `${image_name}.png` - const width = html_manip.getWidth() - const height = html_manip.getHeight() - - //get the selection from the canvas as base64 png, make sure to resize to the width and height slider - const selectionInfo = g_generation_session.selectionInfo - - const use_silent_mode = html_manip.getUseSilentMode() - - const base64_image = - await io.IO.getSelectionFromCanvasAsBase64Interface( - width, - height, - layer, - selectionInfo, - true, - use_silent_mode, - image_name - ) - - //save base64 as file in the init_images directory - const init_entry = await getInitImagesDir() - await io.IO.base64PngToPngFile(base64_image, init_entry, image_name) - - g_init_image_mask_name = image_name // this is the name we will send to the server - - console.log(image_name) - - const path = `${g_init_images_dir}/${image_name}` - g_generation_session.base64maskImage[path] = base64_image - g_generation_session.activeBase64MaskImage = base64_image - - const mask_src = base64ToSrc(g_generation_session.activeBase64MaskImage) - html_manip.setInitImageMaskSrc(mask_src) - return (image_info = { name: image_name, base64: base64_image }) - } catch (e) { - console.error(`psapi.js setInitImageMask error: `, e) - } -} - -// remove the generated mask related layers from the canvas and "layers" panel - -// async function cleanSnapAndFill(layers){ -// // we can delete this function and use cleanLayers() instead -// //delete init image group -// //delete init image (snapshot layer) -// //delete fill layer - -// for (layer of layers){ -// try{ - -// await executeAsModal(async ()=>{await layer.delete()}) -// }catch(e){ -// console.warn("cleanSnapAndFill, issue deleting a layer",e) -// } -// } -// return [] -// } - async function cleanLayers(layers) { // g_init_image_related_layers = {} // g_mask_related_layers = {} @@ -1488,9 +1347,7 @@ module.exports = { layerToFileName, layerNameToFileName, - // cleanLayersOutpaint, - // cleanLayersInpaint, - // cleanSnapAndFill, + cleanLayers, createClippingMaskExe, checkIfSelectionAreaIsActive, @@ -1505,8 +1362,7 @@ module.exports = { isSelectionValid, snapshot_layer_no_slide_Exe, setVisibleExe, - silentSetInitImage, - silentSetInitImageMask, + executeCommandExe, executeDescExe, getSelectionInfoCommand, diff --git a/sdapi_py_re.js b/sdapi_py_re.js index 1a5f2b5..b6cb2d3 100644 --- a/sdapi_py_re.js +++ b/sdapi_py_re.js @@ -1,6 +1,6 @@ const { getDummyBase64, getDummyBase64_2 } = require('./utility/dummy') const { base64ToBase64Url } = require('./utility/general') -const { getExtensionType } = require('./utility/html_manip') + const py_re = require('./utility/sdapi/python_replacement') const Enum = require('./enum') const { control_net } = require('./typescripts/dist/bundle') @@ -72,60 +72,6 @@ async function requestProgress() { return null } -async function requestGetModels() { - console.log('requestGetModels: ') - let json = [] - const full_url = `${g_sd_url}/sdapi/v1/sd-models` - try { - let request = await fetch(full_url) - json = await request.json() - console.log('models json:') - console.dir(json) - } catch (e) { - console.warn(`issues requesting from ${full_url}`, e) - } - return json -} - -async function requestGetSamplers() { - let json = null - try { - console.log('requestGetSamplers: ') - - const full_url = `${g_sd_url}/sdapi/v1/samplers` - let request = await fetch(full_url) - json = await request.json() - // console.log('samplers json:', json) - } catch (e) { - console.warn(e) - } - return json -} - -async function requestSwapModel(model_title) { - console.log('requestSwapModel: ') - - const full_url = `${g_sd_url}/sdapi/v1/options` - payload = { - sd_model_checkpoint: model_title, - } - let request = await fetch(full_url, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload), - }) - - let json = await request.json() - - console.log('models json:') - console.dir(json) - - return json -} - async function requestInterrupt() { const full_url = `${g_sd_url}/sdapi/v1/interrupt` try { @@ -151,13 +97,6 @@ async function requestInterrupt() { } } -async function getVersionRequest() { - console.log('requestGetSamplers: ') - const current_version = g_version - - return current_version -} - async function changeSdUrl(new_sd_url) { // version = "v0.0.0" console.log('changeSdUrl: new_sd_url:', new_sd_url) @@ -229,24 +168,6 @@ async function savePromptShortcut(prompt_shortcut) { return json['prompt_shortcut'] } -async function setInpaintMaskWeight(value) { - const full_url = `${g_sd_url}/sdapi/v1/options` - try { - const payload = { - inpainting_mask_weight: value, - } - await fetch(full_url, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload), - }) - } catch (e) { - console.warn(e) - } -} async function requestGetConfig() { console.log('requestGetConfig: ') @@ -439,21 +360,6 @@ async function requestExtraSingleImage(payload) { } } -async function requestGetUpscalers() { - console.log('requestGetUpscalers: ') - let json = [] - const full_url = `${g_sd_url}/sdapi/v1/upscalers` - try { - let request = await fetch(full_url) - json = await request.json() - console.log('upscalers json:') - console.dir(json) - } catch (e) { - console.warn(`issues requesting from ${full_url}`, e) - } - return json -} - //REFACTOR: reuse the same code for (requestControlNetTxt2Img,requestControlNetImg2Img) async function requestControlNetTxt2Img(plugin_settings) { console.log('requestControlNetTxt2Img: ') @@ -649,26 +555,20 @@ async function isWebuiRunning() { } return true } -async function requestLoraModels() { - const full_url = `${g_sd_url}/sdapi/v1/loras` - const lora_models = (await api.requestGet(full_url)) ?? [] - return lora_models -} + module.exports = { requestTxt2Img, requestImg2Img, requestProgress, - requestGetModels, - requestSwapModel, + requestInterrupt, - requestGetSamplers, - getVersionRequest, + changeSdUrl, loadPromptShortcut, savePromptShortcut, loadHistory, - setInpaintMaskWeight, + requestGetConfig, requestGetOptions, imageSearch, @@ -677,9 +577,8 @@ module.exports = { // requestHordeCheck, // requestHordeStatus, requestExtraSingleImage, - requestGetUpscalers, + requestControlNetTxt2Img, requestControlNetImg2Img, isWebuiRunning, - requestLoraModels, } diff --git a/selection.js b/selection.js index f57afe6..980c099 100644 --- a/selection.js +++ b/selection.js @@ -767,25 +767,16 @@ class Selection { static reselectArea(selection_info) {} static isSameSelection(selection_info_1, selection_info_2) {} static async getImageToSelectionDifference() { - const selectionInfo = await psapi.getSelectionInfoExe() + // const selectionInfo = await psapi.getSelectionInfoExe() + // const width = html_manip.getWidth() + // const height = html_manip.getHeight() - const width = html_manip.getWidth() - const height = html_manip.getHeight() - const scale_info_str = `${parseInt(width)}x${parseInt( - height - )} => ${parseInt(selectionInfo.width)}x${parseInt( - selectionInfo.height - )} ` + const selectionInfo = session_store.data.current_selection_info + const width = sd_tab_store.data.width + const height = sd_tab_store.data.height let ratio = (width * height) / (selectionInfo.width * selectionInfo.height) - // const arrow = percentage >= 1 ? '↑' : '↓' - // percentage = percentage >= 1 ? percentage : 1 / percentage - - // const percentage_str = `${arrow}X${percentage.toFixed(2)}` - - // console.log('scale_info_str: ', scale_info_str) - // console.log('percentage_str: ', percentage_str) return ratio } static {} @@ -1018,7 +1009,8 @@ async function black_white_layer_to_mask(mask_id, target_layer_id, mask_name) { async function black_white_layer_to_mask_multi_batchplay( mask_id, target_layer_id, - mask_name + mask_name, + expand_by = 10 ) { let result let psAction = require('photoshop').action @@ -1063,7 +1055,7 @@ async function black_white_layer_to_mask_multi_batchplay( _obj: 'expand', by: { _unit: 'pixelsUnit', - _value: 10, + _value: expand_by, }, selectionModifyEffectAtCanvasBounds: true, _isCommand: true, diff --git a/typescripts/after_detailer/after_detailer.tsx b/typescripts/after_detailer/after_detailer.tsx index 5f61166..46d5298 100644 --- a/typescripts/after_detailer/after_detailer.tsx +++ b/typescripts/after_detailer/after_detailer.tsx @@ -10,24 +10,20 @@ import { SpMenu, SpSliderWithLabel, } from '../util/elements' +import { Collapsible } from '../util/collapsible' // import * as sdapi from '../../sdapi_py_re' import { api } from '../util/oldSystem' import { AStore } from '../main/astore' import { ui_config, model_list } from './config' const { requestGet } = api import { requestControlNetModelList } from '../controlnet/entry' +import { ErrorBoundary } from '../util/errorBoundary' +import { ScriptMode } from '../util/ts/enum' import './style/after_detailer.css' declare let g_sd_url: string -export enum ScriptMode { - Txt2Img = 'txt2img', - Img2Img = 'img2img', - Inpaint = 'inpaint', - Outpaint = 'outpaint', -} - export let script_mode = [ ScriptMode.Img2Img, ScriptMode.Inpaint, @@ -263,77 +259,6 @@ export class AfterDetailerComponent extends React.Component<{ const domNode = document.getElementById('alwaysOnScriptsContainer')! const root = ReactDOM.createRoot(domNode) -import { useState, ReactNode } from 'react' -import Locale from '../locale/locale' -import { ErrorBoundary } from '../util/errorBoundary' - -interface CollapsibleProps { - label: string - labelStyle?: React.CSSProperties - containerStyle?: React.CSSProperties - defaultIsOpen?: boolean - checked?: boolean - checkboxCallback?: (checked: boolean) => void - children: ReactNode -} - -function Collapsible({ - label, - labelStyle, - containerStyle, - defaultIsOpen = false, - checkboxCallback, - checked, - children, -}: CollapsibleProps) { - const [isOpen, setIsOpen] = useState(defaultIsOpen) - - const handleToggle = () => { - setIsOpen(!isOpen) - } - - return ( - /*useObserver(()=>*/
-
- - {label} - - - - {checkboxCallback && checked !== void 0 ? ( - { - event.stopPropagation() - }} - onChange={(event: any) => { - checkboxCallback(event.target.checked) - }} - checked={checked} - /> - ) : ( - void 0 - )} - - {isOpen ? '∨' : '<'} - -
- {/* {isOpen &&
{children}
} */} -
{children}
-
- ) -} - -export default Collapsible - root.render( diff --git a/typescripts/controlnet/ControlNetTab.tsx b/typescripts/controlnet/ControlNetTab.tsx index 65f4e09..c40982f 100644 --- a/typescripts/controlnet/ControlNetTab.tsx +++ b/typescripts/controlnet/ControlNetTab.tsx @@ -1,18 +1,19 @@ import { observer } from 'mobx-react' import React from 'react' import ControlNetUnit from './ControlNetUnit' -import { store as ControlNetStore } from './main' + +import ControlNetStore from './store' import { DefaultControlNetUnitData } from './store' -import { - Enum, - controlnet_preset, - note, - preset, - selection, -} from '../util/oldSystem' -import { SpMenuComponent } from '../util/elements' +import { Enum, controlnet_preset, note, selection } from '../util/oldSystem' +import { SpMenu, SpMenuComponent } from '../util/elements' import Locale from '../locale/locale' -import Collapsible from '../after_detailer/after_detailer' +import { Collapsible } from '../util/collapsible' +import { PresetTypeEnum } from '../util/ts/enum' +import { + store as preset_store, + getAllCustomPresetsSettings, + getCustomPresetsNames, +} from '../preset/shared_ui_preset' let g_controlnet_presets: any declare const g_generation_session: any @@ -28,59 +29,57 @@ class ControlNetTab extends React.Component<{ // private presetMenuChildren: JSX.Element[] = [] - onPresetMenuChange(evt: any) { - const preset_index = evt.target.selectedIndex - const preset_name = evt.target.options[preset_index].textContent - ControlNetStore.controlNetUnitData.forEach((dataitem, index) => { - const presetData = g_controlnet_presets[preset_name][index] || {} + // onPresetMenuChange(evt: any) { + // // const preset_index = evt.target.selectedIndex + // // const preset_name = evt.target.options[preset_index].textContent + // ControlNetStore.controlNetUnitData.forEach((dataitem, index) => { + // const presetData = g_controlnet_presets[preset_name][index] || {} - dataitem.enabled = - presetData.enabled || DefaultControlNetUnitData.enabled - dataitem.input_image = - presetData.input_image || DefaultControlNetUnitData.input_image - dataitem.mask = presetData.mask || DefaultControlNetUnitData.mask + // dataitem.enabled = + // presetData.enabled || DefaultControlNetUnitData.enabled + // dataitem.input_image = + // presetData.input_image || DefaultControlNetUnitData.input_image + // dataitem.mask = presetData.mask || DefaultControlNetUnitData.mask - dataitem.module = - presetData.module || DefaultControlNetUnitData.module - dataitem.model = presetData.model || DefaultControlNetUnitData.model - dataitem.weight = - presetData.weight || DefaultControlNetUnitData.weight - dataitem.resize_mode = - presetData.resize_mode || DefaultControlNetUnitData.resize_mode - dataitem.lowvram = - presetData.lowvram || DefaultControlNetUnitData.lowvram - dataitem.processor_res = - presetData.processor_res || - DefaultControlNetUnitData.processor_res - dataitem.threshold_a = - presetData.threshold_a || DefaultControlNetUnitData.threshold_a - dataitem.threshold_b = - presetData.threshold_b || DefaultControlNetUnitData.threshold_b - dataitem.guidance_start = - presetData.guidance_start || - DefaultControlNetUnitData.guidance_start - dataitem.guidance_end = - presetData.guidance_end || - DefaultControlNetUnitData.guidance_end - dataitem.guessmode = - presetData.guessmode || DefaultControlNetUnitData.guessmode + // dataitem.module = + // presetData.module || DefaultControlNetUnitData.module + // dataitem.model = presetData.model || DefaultControlNetUnitData.model + // dataitem.weight = + // presetData.weight || DefaultControlNetUnitData.weight + // dataitem.resize_mode = + // presetData.resize_mode || DefaultControlNetUnitData.resize_mode + // dataitem.lowvram = + // presetData.lowvram || DefaultControlNetUnitData.lowvram + // dataitem.processor_res = + // presetData.processor_res || + // DefaultControlNetUnitData.processor_res + // dataitem.threshold_a = + // presetData.threshold_a || DefaultControlNetUnitData.threshold_a + // dataitem.threshold_b = + // presetData.threshold_b || DefaultControlNetUnitData.threshold_b + // dataitem.guidance_start = + // presetData.guidance_start || + // DefaultControlNetUnitData.guidance_start + // dataitem.guidance_end = + // presetData.guidance_end || + // DefaultControlNetUnitData.guidance_end + // dataitem.guessmode = + // presetData.guessmode || DefaultControlNetUnitData.guessmode - dataitem.control_mode = - presetData.control_mode || - DefaultControlNetUnitData.control_mode - dataitem.pixel_perfect = - presetData.pixel_perfect || - DefaultControlNetUnitData.pixel_perfect - }) - } + // dataitem.control_mode = + // presetData.control_mode || + // DefaultControlNetUnitData.control_mode + // dataitem.pixel_perfect = + // presetData.pixel_perfect || + // DefaultControlNetUnitData.pixel_perfect + // }) + // } // function to update presetMenuChildren updatePresetMenuChildren(newChildren: any) { this.setState({ presetMenuChildren: newChildren }) } async updatePresetMenuEvent() { - const custom_presets = await preset.getAllCustomPresetsSettings( - Enum.PresetTypeEnum['ControlNetPreset'] - ) + const custom_presets = await getAllCustomPresetsSettings() g_controlnet_presets = { 'Select CtrlNet Preset': {}, ...controlnet_preset.ControlNetNativePresets, @@ -147,25 +146,25 @@ class ControlNetTab extends React.Component<{ render() { return (
- { + console.log('value:', value) + + preset_store.data.current_controlnet_preset = value.item + // this.onPresetMenuChange() }} - > - - {this.state.presetMenuChildren.map((child) => child)} - - + > */} +
{this.props.appState.maxControlNet == 0 && (
-
+
- - {!pd.model_free && ( +
+
+ {!pd.model_free && ( +
+ +
)}
diff --git a/typescripts/controlnet/entry.ts b/typescripts/controlnet/entry.ts index 53e62a7..ea7f967 100644 --- a/typescripts/controlnet/entry.ts +++ b/typescripts/controlnet/entry.ts @@ -1,8 +1,14 @@ import { setControlImageSrc } from '../../utility/html_manip' -import { session_ts } from '../entry' +// import { session_ts } from '../entry' +// import * as session_ts from '../session/session' +import { store as session_store } from '../session/session_store' import { Enum, api, python_replacement } from '../util/oldSystem' import { GenerationModeEnum } from '../util/ts/enum' -import { store, versionCompare } from './main' +import store, { + DefaultControlNetUnitData, + DefaultPresetControlNetUnitData, + controlNetUnitData, +} from './store' const { getExtensionUrl } = python_replacement declare const g_sd_config_obj: any @@ -122,13 +128,11 @@ function mapPluginSettingsToControlNet(plugin_settings: any) { let input_image = store.controlNetUnitData[index].input_image if ( b_sync_input_image && - [GenerationModeEnum.Txt2Img].includes( - session_ts.store.data.mode - ) + [GenerationModeEnum.Txt2Img].includes(session_store.data.mode) ) { //conditions: 1) txt2img mode 2)auto image on 3)first generation of session - input_image = session_ts.store.data.controlnet_input_image ?? '' + input_image = session_store.data.controlnet_input_image ?? '' store.controlNetUnitData[index].input_image = input_image } if ( @@ -138,10 +142,10 @@ function mapPluginSettingsToControlNet(plugin_settings: any) { GenerationModeEnum.Inpaint, GenerationModeEnum.Outpaint, GenerationModeEnum.LassoInpaint, - ].includes(session_ts.store.data.mode) + ].includes(session_store.data.mode) ) { // img2img mode - input_image = session_ts.store.data.init_image + input_image = session_store.data.init_image store.controlNetUnitData[index].input_image = input_image } else if ( b_sync_input_image && @@ -160,7 +164,7 @@ function mapPluginSettingsToControlNet(plugin_settings: any) { // const b_sync_input_image = // store.controlNetUnitData[index].auto_image // let mask = store.controlNetUnitData[index].mask // the user created mask - // if (b_sync_input_image && session_ts.store.data.expanded_mask) { + // if (b_sync_input_image && session_store.data.expanded_mask) { // //use the mask from inpaint and outpaint mode // mask = '' // this will tell controlnet to use SD mask // store.controlNetUnitData[index].mask = '' @@ -170,7 +174,7 @@ function mapPluginSettingsToControlNet(plugin_settings: any) { [ GenerationModeEnum.Txt2Img, GenerationModeEnum.Img2Img, - ].includes(session_ts.store.data.mode) + ].includes(session_store.data.mode) ) { //maskless mode } else { @@ -190,7 +194,7 @@ function mapPluginSettingsToControlNet(plugin_settings: any) { module: store.controlNetUnitData[index].module, model: store.controlNetUnitData[index].model, weight: store.controlNetUnitData[index].weight, - resize_mode: 'Scale to Fit (Inner Fit)', + resize_mode: 'Crop and Resize', lowvram: store.controlNetUnitData[index].lowvram, processor_res: store.controlNetUnitData[index].processor_res || 512, threshold_a: store.controlNetUnitData[index].threshold_a, @@ -234,6 +238,24 @@ function getControlNetMaxModelsNumber() { function getUnitsData() { return store.controlNetUnitData } + +export function setUnitData(unitData: controlNetUnitData, index: number) { + try { + store.controlNetUnitData[index] = { + ...store.controlNetUnitData[index], + ...unitData, + } + + if (!unitData?.enabled) { + store.controlNetUnitData[index] = { + ...store.controlNetUnitData[index], + ...DefaultPresetControlNetUnitData, + } + } + } catch (e) { + console.error(e) + } +} function setControlDetectMapSrc(base64: string, index: number) { // store.controlNetUnitData[index].mask = base64 store.controlNetUnitData[index].detect_map = base64 diff --git a/typescripts/controlnet/main.tsx b/typescripts/controlnet/main.tsx index 1251e01..5d3316e 100644 --- a/typescripts/controlnet/main.tsx +++ b/typescripts/controlnet/main.tsx @@ -3,7 +3,7 @@ import React from 'react' import ControlNetTab from './ControlNetTab' import store from './store' import { versionCompare } from './util' -import Collapsible from '../after_detailer/after_detailer' +import { Collapsible } from '../util/collapsible' import Locale from '../locale/locale' import { ErrorBoundary } from '../util/errorBoundary' @@ -48,51 +48,9 @@ if (elem2) { } function scrollToEnabledControlNetUnit() {} -const button = document.getElementById('scrollToControlNetUnitContainer')! -const button_root = ReactDOM.createRoot(button) -let controlnet_unit_index = 0 -button_root.render( - - - -) - -export { store, versionCompare } +export { versionCompare } diff --git a/typescripts/controlnet/store.ts b/typescripts/controlnet/store.ts index 2a42711..aa7cd95 100644 --- a/typescripts/controlnet/store.ts +++ b/typescripts/controlnet/store.ts @@ -1,5 +1,11 @@ import { observable, reaction } from 'mobx' - +type ResizeMode = 'Just Resize' | 'Crop and Resize' | 'Resize and Fill' +export const controlnetModes = [ + 'Balanced', + 'My prompt is more important', + 'ControlNet is more important', +] as const +export type ControlnetMode = (typeof controlnetModes)[number] export const DefaultControlNetUnitData = { enabled: false, input_image: '', @@ -8,7 +14,7 @@ export const DefaultControlNetUnitData = { module: '', model: '', weight: 1.0, - resize_mode: 'Scale to Fit (Inner Fit)', + resize_mode: 'Crop and Resize' as ResizeMode, lowvram: true, processor_res: 512, threshold_a: 0, @@ -18,17 +24,37 @@ export const DefaultControlNetUnitData = { guidance_end: 1, guessmode: false, - control_mode: 'Balanced', + control_mode: 'Balanced' as ControlnetMode, pixel_perfect: true, auto_image: true, } -export const controlnetModes = [ - 'Balanced', - 'My prompt is more important', - 'ControlNet is more important', -] as const -export type ControlnetMode = (typeof controlnetModes)[number] +export const DefaultPresetControlNetUnitData = { + enabled: false, + // input_image: '', + // mask: '', + // detect_map: '', + module: '', + model: '', + filter_keyword: 'All', + weight: 1.0, + + resize_mode: 'Crop and Resize' as ResizeMode, + + lowvram: true, + + processor_res: 512, + threshold_a: 0, + threshold_b: 0, + + guidance_start: 0, + guidance_end: 1, + guessmode: false, + + control_mode: 'Balanced' as ControlnetMode, + pixel_perfect: true, + auto_image: true, +} export interface controlNetUnitData { enabled: boolean @@ -41,7 +67,7 @@ export interface controlNetUnitData { model: string filter_keyword: string weight: number - resize_mode: 'Just Resize' | 'Crop and Resize' | 'Resize and Fill' + resize_mode: ResizeMode lowvram: boolean processor_res: number threshold_a: number diff --git a/typescripts/entry.ts b/typescripts/entry.ts index 0a044cd..1062816 100644 --- a/typescripts/entry.ts +++ b/typescripts/entry.ts @@ -1,24 +1,38 @@ -// import { configure } from 'mobx' -// configure({ -// enforceActions: 'never', // disable mobx warning temporarily -// }) +import { configure } from 'mobx' +configure({ + enforceActions: 'never', // disable mobx warning temporarily +}) export * as control_net from './controlnet/entry' export * as after_detailer_script from './after_detailer/after_detailer' export * as ultimate_sd_upscaler from './ultimate_sd_upscaler/ultimate_sd_upscaler' export * as scripts from './ultimate_sd_upscaler/scripts' export * as main from './main/main' +export * as controlnet_main from './controlnet/main' export * as logger from './util/logger' export * as image_search from './image_search/image_search' export * as history from './history/history' export * as viewer from './viewer/viewer' export * as session_ts from './session/session' +export { store as session_store } from './session/session_store' +export { store as sd_tab_store } from './sd_tab/util' + export * as progress from './session/progress' export * as preview from './viewer/preview' export * as generate from './session/generate' export * as sd_tab_ts from './sd_tab/sd_tab' +export * as sd_tab_util from './sd_tab/util' export * as sam from './sam/sam' export * as settings_tab_ts from './settings/settings' export * as one_button_prompt from './one_button_prompt/one_button_prompt' export * as enum_ts from './util/ts/enum' export * as multiPrompts from './multiTextarea' +export * as preset from './preset/preset' +export * as preset_util from './preset/shared_ui_preset' +export * as ui_ts from './util/ts/ui_ts' +export * as io_ts from './util/ts/io' +export * as tool_bar from './tool_bar/tool_bar' +export * as extra_page from './extra_page/extra_page' +export * as selection_ts from './util/ts/selection' +export * as stores from './stores' export { toJS } from 'mobx' +export { default as node_fs } from 'fs' diff --git a/typescripts/extra_page/extra_page.tsx b/typescripts/extra_page/extra_page.tsx new file mode 100644 index 0000000..bb08708 --- /dev/null +++ b/typescripts/extra_page/extra_page.tsx @@ -0,0 +1,267 @@ +import { observer } from 'mobx-react' +import React from 'react' +import ReactDOM from 'react-dom/client' +import { ErrorBoundary } from '../util/errorBoundary' +import { Collapsible } from '../util/collapsible' +import { GenerateButtons } from '../session/generate' +import { AStore } from '../main/astore' +import { SpMenu, SpSlider } from '../util/elements' +import { mapRange } from '../controlnet/util' +import { requestGetUpscalers } from '../util/ts/sdapi' + +export const store = new AStore({ + upscaling_resize: 2, + upscaler_list: [] as string[], + upscaler_1: '', + upscaler_2: '', + resize_mode: 0, + show_extras_results: 0, + gfpgan_visibility: 0, + codeformer_visibility: 0, + codeformer_weight: 0, + upscaling_resize_w: 0, + upscaling_resize_h: 0, + upscaling_crop: true, + extras_upscaler_2_visibility: 0, + upscale_first: false, +}) + +export async function refreshExtraUpscalers() { + try { + const upscalers = await requestGetUpscalers() + if (upscalers) { + store.data.upscaler_list = upscalers.map( + (upscaler: { name: any }) => upscaler.name + ) + } + } catch (e) { + console.error(e) + } +} +@observer +export class ExtraPage extends React.Component { + componentDidMount(): void {} + + render(): React.ReactNode { + return ( +
+
+ { + store.data.upscaling_resize = mapRange( + evt.target.value, + 10, + 80, + 1, + 8, + 0.01 + ) + }} + > + Resize + + {store.data.upscaling_resize.toFixed(2)} + + +
+ + +
+ + No work in progress + +
+
+ + Upscaler 1: + + { + store.data.upscaler_1 = value.item + }} + > + +
+ + Upscaler 2: + + { + store.data.upscaler_2 = value.item + }} + > +
+
+ { + store.data.extras_upscaler_2_visibility = + evt.target.value / 10 + }} + > + + Upscaler 2 visibility: + + + {store.data.extras_upscaler_2_visibility.toFixed(2)} + + +
+
+ { + store.data.gfpgan_visibility = evt.target.value / 10 + }} + > + + GFPGAN visibility: + + + {store.data.gfpgan_visibility.toFixed(2)} + + +
+
+ { + store.data.codeformer_visibility = + evt.target.value / 10 + }} + > + + CodeFormer visibility: + + + {store.data.codeformer_visibility.toFixed(2)} + + +
+
+ { + store.data.codeformer_weight = evt.target.value / 10 + }} + > + + CodeFormer weight: + + + {store.data.codeformer_weight.toFixed(2)} + + +
+
+ ) + } +} + +const containers = document.querySelectorAll('.extraPageContainer')! + +containers.forEach((container) => { + const root = ReactDOM.createRoot(container) + + root.render( + + +
+ + + +
+
+
+ ) +}) diff --git a/typescripts/history/history.tsx b/typescripts/history/history.tsx index 279af28..69f2ced 100644 --- a/typescripts/history/history.tsx +++ b/typescripts/history/history.tsx @@ -8,10 +8,11 @@ import { MoveToCanvasSvg, PenSvg } from '../util/elements' import { ErrorBoundary } from '../util/errorBoundary' import Locale from '../locale/locale' import { addWithHistory } from '../viewer/viewer' -import Collapsible from '../after_detailer/after_detailer' +import { Collapsible } from '../util/collapsible' //@ts-ignore import { storage } from 'uxp' import { _arrayBufferToBase64 } from '../util/ts/io' +import { sd_tab_store } from '../stores' declare let g_ui_settings_object: any export const store = new AStore({ images: [] as string[], //full resloution images @@ -134,7 +135,7 @@ async function moveHistoryImageToLayer( // width, // height // ) - debugger + const layer = await addWithHistory( base64_image, metadata?.expanded_mask ?? void 0, @@ -146,12 +147,12 @@ async function moveHistoryImageToLayer( } } +function historyMetadataToPreset(metadata: any) {} function getHistoryMetadata(metadata_json: any) { //auto fill the ui with metadata // const metadata_json = JSON.parse(img.dataset.metadata_json_string) console.log('metadata_json: ', metadata_json) - // document.querySelector('#tiSeed').value = metadata_json.Seed //extract auto_metadata into the preset metadata function convertAutoMetadataToPreset(metadata_json: any) { @@ -220,7 +221,7 @@ function segmentCombinedArray(combinedArray: CombinedElement[]) { const segmentedArray: CombinedElement[][] = [] let currentSessionId = combinedArray[0].metadata_json.session_id let currentSegment: CombinedElement[] = [] - debugger + for (const element of combinedArray) { if (element.metadata_json.session_id === currentSessionId) { currentSegment.push(element) diff --git a/typescripts/lexical/lexical.tsx b/typescripts/lexical/lexical.tsx new file mode 100644 index 0000000..6074f2c --- /dev/null +++ b/typescripts/lexical/lexical.tsx @@ -0,0 +1,58 @@ +//TODO: delete lexical_tab.js and lexica tab from html +import { observer } from 'mobx-react' +import React from 'react' + +@observer +export class Lexical extends React.Component { + componentDidMount(): void {} + componentWillUnmount(): void {} + + render() { + return ( +
+
+ +
+ + Explore Lexica for prompts and inspiration + +
+
+
+ + Search: + + + + + +
+ +
+ +
+
+ ) + } +} diff --git a/typescripts/multiTextarea.tsx b/typescripts/multiTextarea.tsx index e32cbae..e430a7a 100644 --- a/typescripts/multiTextarea.tsx +++ b/typescripts/multiTextarea.tsx @@ -3,7 +3,7 @@ import React from 'react' import ReactDOM from 'react-dom/client' import { AStore } from './main/astore' import { ErrorBoundary } from './util/errorBoundary' -import Collapsible from './after_detailer/after_detailer' +import { Collapsible } from './util/collapsible' interface AStoreData { positivePrompts: string[] @@ -14,8 +14,8 @@ interface AStoreData { const defaultPositivePrompt = 'cute cat, {painterly_style_1}' const defaultNegativePrompt = '{ugly}' export const store = new AStore({ - positivePrompts: Array(4).fill(defaultPositivePrompt), - negativePrompts: Array(4).fill(defaultNegativePrompt), + positivePrompts: [defaultPositivePrompt, ...Array(3).fill('')], + negativePrompts: [defaultNegativePrompt, ...Array(3).fill('')], current_index: 0, }) @@ -134,20 +134,20 @@ export class MultiTextArea extends React.Component { } } -const containers = document.querySelectorAll('.multiPromptsContainer')! +// const containers = document.querySelectorAll('.multiPromptsContainer')! -containers.forEach((container) => { - const root = ReactDOM.createRoot(container) +// containers.forEach((container) => { +// const root = ReactDOM.createRoot(container) - root.render( - - -
- - - -
-
-
- ) -}) +// root.render( +// +// +//
+// +// +// +//
+//
+//
+// ) +// }) diff --git a/typescripts/one_button_prompt/one_button_prompt.tsx b/typescripts/one_button_prompt/one_button_prompt.tsx index 0a2d8e5..7e0f08c 100644 --- a/typescripts/one_button_prompt/one_button_prompt.tsx +++ b/typescripts/one_button_prompt/one_button_prompt.tsx @@ -1,7 +1,7 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import Collapsible from '../after_detailer/after_detailer' +import { Collapsible } from '../util/collapsible' import { observer } from 'mobx-react' import { AStore } from '../main/astore' @@ -154,45 +154,57 @@ class OneButtonPrompt extends React.Component { store.data.prompt_complexity = output_value }} /> - Subject: - { - // console.log('onChange value: ', value) - store.updateProperty('subject', value.item) - }} - > - Artist: - { - // console.log('onChange value: ', value) - store.updateProperty('artist', value.item) - }} - > - Image Type: - { - // console.log('onChange value: ', value) - store.updateProperty('imagetype', value.item) - }} - > +
+ { + // console.log('onChange value: ', value) + store.updateProperty('subject', value.item) + }} + > + + Subject + +
+
+ { + // console.log('onChange value: ', value) + store.updateProperty('artist', value.item) + }} + > + + Artist + +
+
+ { + // console.log('onChange value: ', value) + store.updateProperty('imagetype', value.item) + }} + > + + Image Type + +
{ + return preset_tab_store.data.new_preset + }, + (current_preset: any) => { + try { + const text = JSON.stringify(current_preset, undefined, 7) || '' + const textarea_element = document.getElementById( + 'taPresetSettings' + ) as any + textarea_element.value = text + updateTextAreaHeight(textarea_element) + } catch (e) { + console.error(e) + } + } +) + +function getPresetSettingsHtml() { + //@ts-ignore + const value_str = document.getElementById('taPresetSettings')!.value + const value_json = JSON.parse(value_str) + return value_json +} + +function updateTextAreaHeight(textarea_element: any) { + try { + //update the height of the text area to fit the settings in + + const new_lines_count = general.countNewLines(textarea_element.value) + let height = new_lines_count * 12 + 100 + height = Math.max(60, height) + height = Math.min(500, height) + textarea_element.style.height = height.toString() + 'px' + } catch (e) { + console.error(e) + } +} + +// function setPresetName(preset_name: string) { +// //@ts-ignore +// document.getElementById('tiPresetName')!.value = preset_name +// } + +async function deletePreset() { + try { + const preset_file_name = + preset_tab_store.data.selected_preset_name + '.json' + + const custom_preset_entry = await io.IOFolder.getCustomPresetFolder( + 'custom_preset' + ) + + await io.IOJson.deleteFile(custom_preset_entry, preset_file_name) + preset_tab_store.data.selected_preset_name = '' + preset_tab_store.data.new_preset = {} + store.data.custom_presets = await getAllCustomPresetsSettings() + } catch (e) { + console.error(e) + } +} +function filterControlnetUnitData(controlnet_units_data: controlNetUnitData[]) { + const filtered_data = controlnet_units_data.map((unit) => { + const { + input_image, + mask, + detect_map, + model_list, + module_list, + ...rest + } = unit + return rest + }) + return filtered_data +} + +export function onNewPreset() { + const sd_tab_preset = storeToPreset(sd_tab_store) + const controlnet_tab_preset = toJS(getUnitsData()) + + const units = controlnet_tab_preset.map((unit: controlNetUnitData) => { + if (unit.enabled === false) return {} + else { + const { + input_image, + mask, + detect_map, + model_list, + module_list, + ...rest + } = unit + return rest + } + }) + + const plugin_preset = { + sd_tab_preset: sd_tab_preset, + controlnet_tab_preset: units, + } + preset_tab_store.data.new_preset = plugin_preset + return plugin_preset +} + +async function onSavePreset() { + if (preset_tab_store.data.new_preset_name) { + const preset_settings = getPresetSettingsHtml() + const preset_name = preset_tab_store.data.new_preset_name.trim() + const preset_file_name = preset_name + '.json' // will be used as file name + //check if the file exist and prompt the user to override it or cancel + + const custom_preset_entry = await io.IOFolder.getCustomPresetFolder( + 'custom_preset' + ) + await io.IOJson.saveJsonToFileExe( + preset_settings, + custom_preset_entry, + preset_file_name + ) + store.data.custom_presets = await getAllCustomPresetsSettings() + + console.log('store.data.custom_presets: ', store.data.custom_presets) + preset_tab_store.data.selected_preset_name = preset_name + } +} + +@observer +class PresetTab extends React.Component<{}> { + async componentDidMount() { + // await populatePresetMenu() + try { + store.data.custom_presets = await getAllCustomPresetsSettings() + + // store.data.controlnet_native_presets = { + // ...controlnet_preset.ControlNetNativePresets, + // } + } catch (e) { + console.error(e) + } + } + renderTab() { + return ( +
+ { + preset_tab_store.data.new_preset_name = + event.target.value + // console.log(store.data.preset_name) + }} + > + +
+ + +
+
+ { + // console.log('onChange value: ', value) + // store.updateProperty('subject', value.item) + console.log('value:', value) + preset_tab_store.data.selected_preset_name = + value.item + preset_tab_store.data.new_preset_name = value.item + preset_tab_store.data.new_preset = + store.data.custom_presets[value.item] + }} + > +
+
+ + {preset_tab_store.data.new_preset_name.trim()} + +
+
+ { + console.log('onChange:') + updateTextAreaHeight(event.target) + }} + onInput={(event: any) => { + console.log('onInput:') + updateTextAreaHeight(event.target) + }} + > +
+
+ ) + } + render(): React.ReactNode { + return this.renderTab() + } +} + +const gridContainerNode = document.getElementById('PresetTabContainer')! +const gridRoot = ReactDOM.createRoot(gridContainerNode) + +gridRoot.render( + + +
+ + + +
+
+
+) diff --git a/typescripts/preset/shared_ui_preset.ts b/typescripts/preset/shared_ui_preset.ts new file mode 100644 index 0000000..e8f5438 --- /dev/null +++ b/typescripts/preset/shared_ui_preset.ts @@ -0,0 +1,120 @@ +import { AStore } from '../main/astore' +import { html_manip, io } from '../util/oldSystem' +import { PresetTypeEnum } from '../util/ts/enum' +// import { getNativeSDPresets } from '../util/ts/ui_ts' + +export async function getLoadedPresets(ui_settings_obj: any) { + let customPresets + + customPresets = await mapCustomPresetsToLoaders(ui_settings_obj) + console.log('customPresets: ', customPresets) + let loadedPresets = { + // ...getNativeSDPresets(), + ...customPresets, + } + return loadedPresets +} +export const store = new AStore({ + preset_name: '', + custom_presets: [] as any, + selected_preset_name: '', + + sd_presets: [], + sd_native_presets: [], + + selected_sd_preset_name: '', // the selected sd preset in sd tab + selected_sd_preset: {}, // the selected sd preset settings +}) + +export const preset_tab_store = new AStore({ + new_preset_name: '', //for the textfield field and label + new_preset: {} as any, // settings of the current preset tab preset + selected_preset_name: '', // name of the selected in the menu + selected_preset: {}, //settings of the selected preset in the menu +}) +export async function getCustomPresetEntries(preset_folder_name: string) { + const custom_preset_entry = await io.IOFolder.getCustomPresetFolder( + preset_folder_name + ) + + const custom_preset_entries = await io.IOJson.getJsonEntries( + custom_preset_entry + ) + + return custom_preset_entries +} +export async function loadPresetSettingsFromFile(preset_file_name: string) { + const custom_preset_entry = await io.IOFolder.getCustomPresetFolder( + 'custom_preset' + ) + let preset_settings = {} + try { + preset_settings = await io.IOJson.loadJsonFromFile( + custom_preset_entry, + preset_file_name + ) + } catch (e) { + console.warn(e) + } + return preset_settings +} + +export async function getAllCustomPresetsSettings() { + const custom_preset_entries = await getCustomPresetEntries('custom_preset') + let custom_presets: any = {} + for (const entry of custom_preset_entries) { + const preset_name: string = entry.name.split('.json')[0] + let preset_settings = await loadPresetSettingsFromFile(entry.name) + + custom_presets[preset_name] = preset_settings + } + return custom_presets +} + +const updatePresetMenuEvent = new CustomEvent('updatePresetMenuEvent', { + detail: {}, + bubbles: true, + cancelable: true, + composed: false, +}) + +export function loadPreset(ui_settings: any, preset: any) { + console.log('preset:', preset) + ui_settings.autoFillInSettings(preset) +} +export function loadCustomPreset( + ui_settings_obj: any, + custom_preset_settings: any +) { + loadPreset(ui_settings_obj, custom_preset_settings) +} +export async function mapCustomPresetsToLoaders(ui_settings_obj: any) { + const name_to_settings_obj = await getAllCustomPresetsSettings() + const preset_name_to_loader_obj: any = {} + for (const [preset_name, preset_settings] of Object.entries( + name_to_settings_obj + )) { + preset_name_to_loader_obj[preset_name] = () => { + loadCustomPreset(ui_settings_obj, preset_settings) + } + } + return preset_name_to_loader_obj +} + +export function getCustomPresetsNames(custom_presets: any) { + let presets_names: any = [] + if (custom_presets) { + presets_names = Object.keys(custom_presets) + } + return presets_names +} + +export function onLoadControlnetPreset() {} +export function onLoadSDPreset() {} + +//sd preset = {preset_name: settings_json} +//sd_preset_loader(sd_preset) + +//controlnet_preset = {preset_name: settings_json} + +export { updatePresetMenuEvent } diff --git a/typescripts/sam/sam.tsx b/typescripts/sam/sam.tsx index d4a4e64..583c87a 100644 --- a/typescripts/sam/sam.tsx +++ b/typescripts/sam/sam.tsx @@ -1,6 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import Collapsible from '../after_detailer/after_detailer' +import { Collapsible } from '../util/collapsible' import { observer } from 'mobx-react' import { isScriptInstalled } from '../util/ts/api' import { api, general, io, psapi, selection } from '../util/oldSystem' @@ -11,14 +11,12 @@ import { PenSvg, ScriptInstallComponent, } from '../util/elements' -import { - applyMaskFromBlackAndWhiteImage, - selectionFromBlackAndWhiteImage, -} from '../util/ts/selection' +import { selectionFromBlackAndWhiteImage } from '../util/ts/selection' import { app } from 'photoshop' import { ErrorBoundary } from '../util/errorBoundary' import Locale from '../locale/locale' -import { settings_tab_ts } from '../entry' +// import { settings_tab_ts } from '../entry' +import * as settings_tab_ts from '../settings/settings' import { SelectionInfoType } from '../util/ts/enum' declare let g_sd_url: string diff --git a/typescripts/sd_tab/sd_tab.tsx b/typescripts/sd_tab/sd_tab.tsx index 0952b06..4ef19bf 100644 --- a/typescripts/sd_tab/sd_tab.tsx +++ b/typescripts/sd_tab/sd_tab.tsx @@ -3,16 +3,50 @@ import ReactDOM from 'react-dom/client' import { observer } from 'mobx-react' -import { AStore } from '../main/astore' -import { GenerationModeEnum } from '../util/ts/enum' +import { GenerationModeEnum, ScriptMode } from '../util/ts/enum' import { reaction } from 'mobx' -import { SpCheckBox } from '../util/elements' +import { SpCheckBox, SpMenu, SpSlider, SpTextfield } from '../util/elements' import { ErrorBoundary } from '../util/errorBoundary' +import { Collapsible } from '../util/collapsible' + +import { + store, + refreshModels, + updateClickEventHandler, + tempDisableElement, + refreshUI, + getLoraModelPrompt, + requestLoraModels, + mode_config, + onModeChange, + initInitMaskElement, + widthSliderOnChangeEventHandler, + initPlugin, + helper_store, + viewMaskExpansion, + scaleFromToLabel, + mask_content_config, + requestGetHiResUpscalers, + selection_mode_config, + onWidthSliderInput, + onHeightSliderInput, + heightSliderOnChangeEventHandler, + loadPresetSettings, +} from './util' +import { general } from '../util/oldSystem' +import { requestSwapModel } from '../util/ts/sdapi' +import { GenerateButtons } from '../session/generate' +import { MultiTextArea } from '../multiTextarea' +import { store as progress_store } from '../session/progress' +import { store as session_store } from '../session/session_store' +import { multiPrompts, settings_tab_ts } from '../entry' +import { getExpandedMask } from '../session/session' +import { mapRange } from '../controlnet/util' + +import { store as preset_store } from '../preset/shared_ui_preset' + +declare let g_version: string -export const store = new AStore({ - is_lasso_mode: false, - mode: GenerationModeEnum.Txt2Img, -} as { is_lasso_mode: boolean; mode: GenerationModeEnum }) reaction( () => [store.data.is_lasso_mode, store.data.mode] as [ @@ -57,7 +91,6 @@ const Modes = observer(() => { onChange={handleLassoModeChange} checked={store.data.is_lasso_mode} // id={`chEnableControlNet_${this.props.index}`} - value={store.data.is_lasso_mode} > Lasso Mode @@ -71,13 +104,1216 @@ const Modes = observer(() => { return
{renderLassoModeElement()}
}) -const container = document.getElementById('reactModesContainer')! -const root = ReactDOM.createRoot(container) +// const container = document.getElementById('reactModesContainer')! +// const root = ReactDOM.createRoot(container) -root.render( +// root.render( +// +// +// +// +// +// ) +@observer +class SDTab extends React.Component<{}> { + async componentDidMount() { + try { + await refreshUI() + await refreshModels() + await initPlugin() + helper_store.data.loras = await requestLoraModels() + initInitMaskElement() + helper_store.data.hr_upscaler_list = + await requestGetHiResUpscalers() + const btnSquareClass = document.getElementsByClassName('btnSquare') + //REFACTOR: move to events.js + for (let btnSquareButton of btnSquareClass) { + btnSquareButton.addEventListener('click', async (evt) => { + // document.activeElement.blur() + setTimeout(() => { + try { + //@ts-ignore + evt.target.blur() + } catch (e) { + console.warn(e) + } + }, 500) + }) + } + + // html_manip.sliderAddEventListener_new( + // 'slImageCfgScale', + // 'lImageCfgScale', + // 0, + // 30, + // 0, + // 3 + // ) + + // //REFACTOR: move to events.js + + // //REFACTOR: move to events.js + + // adding a listner here for the inpaint_mask_strengh to be able to use api calls, allowing to dynamicly change the value + // a set button could be added to the ui to reduce the number of api calls in case of a slow connection + // //REFACTOR: move to events.js + // document + // .querySelector('#slInpaintingMaskWeight') + // .addEventListener('input', async (evt) => { + // const label_value = evt.target.value / 100 + // document.getElementById( + // 'lInpaintingMaskWeight' + // ).innerHTML = `${label_value}` + // // await sdapi.setInpaintMaskWeight(label_value) + // }) + // //REFACTOR: move to events.js + // document + // .querySelector('#slInpaintingMaskWeight') + // .addEventListener('change', async (evt) => { + // try { + // const label_value = evt.target.value / 100 + // document.getElementById( + // 'lInpaintingMaskWeight' + // ).innerHTML = `${label_value}` + // await sdapi.setInpaintMaskWeight(label_value) + + // // //get the inpaint mask weight from the webui sd + // // await g_sd_options_obj.getOptions() + // // const inpainting_mask_weight = + // // await g_sd_options_obj.getInpaintingMaskWeight() + + // // console.log('inpainting_mask_weight: ', inpainting_mask_weight) + // // html_manip.autoFillInInpaintMaskWeight(inpainting_mask_weight) + // } catch (e) { + // console.warn(e) + // } + // }) + //REFACTOR: move to events.js + } catch (e) { + console.warn(e) + } + } + render() { + const styles = { + menuBarContainer: { + // display: 'flex', + }, + spMenu: { + // flex: 1, + width: '199px', + marginRight: '3px', + }, + button: { + marginLeft: '3px', + // flex: 0.5, + }, + } + return ( +
+ +
+ { + return lora.name + })} + label_item="Select Lora" + // selected_index={store.data.models + // .map((model) => { + // return model.title + // }) + // .indexOf(store.data.selected_model)} + onChange={(id: any, value: any) => { + const lora_prompt = getLoraModelPrompt(value.item) + const prompt = multiPrompts.getPrompt().positive + multiPrompts.setPrompt({ + positive: `${prompt} ${lora_prompt}`, + }) + }} + > + + + ) => { + settings_tab_ts.store.data.use_prompt_shortcut = + event.target.checked + }} + > + prompt shortcut + +
+
+
+
+ + + Progress... + + + { + progress_store.data.live_progress_image = + evt.target.checked + }} + /> +
+
+ + +
+ + + +
+ + + {mode_config.map((config: any, index: number) => { + return ( + { + await onModeChange(evt.target.value) + }} + checked={ + store.data.rb_mode === config.name + ? true + : void 0 + } + > + {config.name} + + ) + })} + + +
+
+ + + + + + + + +
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+ Batch Size: + { + let value = parseInt(evt.target.value) + if (!isFinite(value) || value < 1) + value = 1 + // evt.target.value = value + store.data.batch_size = value + }} + > +
+
+ Batch Count: + { + store.data.batch_count = parseInt( + evt.target.value + ) + }} + > +
+
+ + Sampling Steps + + { + let value = evt.target.value + store.data.steps = parseInt(value) + }} + > +
+
+
+
+
+ + Selection Mode: + +
+ + +
+ { + onWidthSliderInput(evt.target.value * 64) + }} + onChange={(evt: any) => { + store.data.width + widthSliderOnChangeEventHandler( + evt.target.value * 64, + 64, + 2048 + ) + helper_store.data.previous_width = + store.data.width + }} + > + + Width: + + + {parseInt(store.data.width as any)} + + + + { + onHeightSliderInput(evt.target.value * 64) + }} + onChange={(evt: any) => { + heightSliderOnChangeEventHandler( + evt.target.value * 64, + 64, + 2048 + ) + }} + > + + Height: + + + {parseInt(store.data.height as any)} + + + + {store.data.ratio < 1 ? '↓' : '↑'} + {'x'} + {(store.data.ratio < 1 + ? 1 / store.data.ratio + : store.data.ratio + ).toFixed(2)} + + +
+ +
+ { + store.data.cfg = evt.target.value + }} + > + + CFG Scale: + + + + { + store.data.denoising_strength = + evt.target.value / 100 + }} + > + + Denoising Strength: + + + {store.data.denoising_strength.toFixed(2)} + + +
+ { + store.data.image_cfg_scale = general.mapRange( + evt.target.value, + 0, + 30, + 0, + 3 + ) + }} + > + + Image CFG Scale: + + + {store.data.image_cfg_scale} + + + + { + const mask = + session_store.data.preprocessed_mask + const iterations = store.data.mask_expansion + const mask_blur = parseInt(evt.target.value) + store.data.mask_blur = mask_blur + session_store.data.expanded_mask = + await getExpandedMask( + mask, + iterations, + mask_blur + ) + if (session_store.data.expanded_mask) { + viewMaskExpansion() + } + }} + > + Mask Blur: + + { + const mask = + session_store.data.preprocessed_mask + const iterations = parseInt(evt.target.value) + store.data.mask_expansion = iterations + const mask_blur = store.data.mask_blur + session_store.data.expanded_mask = + await getExpandedMask( + mask, + iterations, + mask_blur + ) + if (session_store.data.expanded_mask) { + viewMaskExpansion() + } + }} + > + Mask Expansion: + + +
+ + + Inpainting conditioning mask strength: + + + 1 + + +
+ +
+ + + Mask Content: + + {mask_content_config.map( + (mask_content, index: number) => { + return ( + { + store.data.inpainting_fill = + mask_content.value + }} + > + {mask_content.name} + + ) + } + )} + +
+ +
+ { + store.data.inpaint_full_res = + evt.target.checked + }} + > + Inpaint at Full Res + + { + store.data.restore_faces = + evt.target.checked + }} + > + Restore Faces + + { + store.data.enable_hr = evt.target.checked + }} + > + Hi Res Fix + +
+
+
+
+ + Upscaler: + + { + store.data.hr_upscaler = value.item + }} + > +
+
+ + Hi Res Steps: + + { + store.data.hr_second_pass_steps = + parseInt(evt.target.value) + }} + > +
+
+
+ { + store.data.hr_scale = mapRange( + evt.target.value, + 1, + 100, + 1, + 4, + 0.1 + ) + }} + > + + Hi Res Scale: + + + {store.data.hr_scale.toFixed(2)} + + + {scaleFromToLabel( + store.data.width, + store.data.height, + store.data.hr_scale + )} + + + { + store.data.hr_denoising_strength = + mapRange( + evt.target.value, + 0, + 100, + 0, + 1, + 0.01 + ) + }} + > + + High Res Denoising Strength: + + + {store.data.hr_denoising_strength.toFixed( + 2 + )} + + + + { + store.data.hr_resize_x = Math.floor( + evt.target.value * 64 + ) + }} + > + + Hi Res Output Width: + + + {store.data.hr_resize_x} + + + + { + store.data.hr_resize_y = Math.floor( + evt.target.value * 64 + ) + }} + > + + Hi Res Output Height: + + + {store.data.hr_resize_y} + + +
+
+ { + const padding = evt.target.value * 4 + store.data.inpaint_full_res_padding = padding + }} + > + + Inpaint Padding: + + + {store.data.inpaint_full_res_padding} + + +
+
+
+ Seed: + { + store.data.seed = evt.target.value + }} + > + + +
+ + + Select Sampler: + {helper_store.data.sampler_list.map( + (sampler: any, index: number) => { + return ( + { + store.data.sampler_name = + sampler.name + }} + > + {sampler.name} + + ) + } + )} + +
+
+
+ ) + } +} + +const sdTabContainer = document.getElementById('sdTabContainer')! +const sdTabRoot = ReactDOM.createRoot(sdTabContainer) +sdTabRoot.render( - + {/*
+ + + +
*/} +
) diff --git a/typescripts/sd_tab/util.ts b/typescripts/sd_tab/util.ts new file mode 100644 index 0000000..3b2773a --- /dev/null +++ b/typescripts/sd_tab/util.ts @@ -0,0 +1,652 @@ +import { control_net, main } from '../entry' +import { AStore } from '../main/astore' +import { script_store } from '../ultimate_sd_upscaler/scripts' +import { ScriptMode } from '../ultimate_sd_upscaler/ultimate_sd_upscaler' +import { + dialog_box, + general, + html_manip, + sampler_data, + settings_tab, + thumbnail, +} from '../util/oldSystem' +import { requestGet } from '../util/ts/api' + +import { GenerationModeEnum, SelectionInfoType } from '../util/ts/enum' +import { + getVersionRequest, + requestGetModels, + requestGetSamplers, + requestGetUpscalers, + setInpaintMaskWeight, +} from '../util/ts/sdapi' +import { store as session_store } from '../session/session_store' +import { setUnitData } from '../controlnet/entry' +import { controlNetUnitData } from '../controlnet/store' +import { presetToStore } from '../util/ts/io' +import { refreshExtraUpscalers } from '../extra_page/extra_page' +declare let g_models: any[] +declare let g_automatic_status: any +declare let g_sd_options_obj: any + +declare let g_controlnet_max_models: number +declare let g_sd_url: string + +export const mode_config = [ + { + name: 'txt2img', + title: 'use this mode to generate images from text only', + id: '', + }, + { + name: 'img2img', + title: 'use this mode to generate variation of an image', + id: '', + }, + { + name: 'inpaint', + title: 'use this mode to generate variation of a small area of an image, while keeping the rest of the image intact', + id: 'rbModeInpaint', + }, + { + name: 'outpaint', + title: 'use this mode to (1) fill any missing area of an image,(2) expand an image', + id: '', + }, +] +export const mask_content_config = [ + { + name: 'fill', + value: 0, + }, + { + name: 'original', + value: 1, + }, + { + name: 'latent noise', + value: 2, + }, + { + name: 'latent nothing', + value: 3, + }, +] +export enum SelectionModeEnum { + Ratio = 'ratio', + Precise = 'precise', + Ignore = 'ignore', +} +export const selection_mode_config = [ + { + name: 'ratio', + value: 'ratio', + title: '', + }, + { + name: 'precise', + value: 'precise', + title: 'use the selection area width and height to fill the width and height sliders', + }, + { + name: 'ignore', + value: 'ignore', + title: 'fill the width and height sliders manually', + }, +] + +export const store = new AStore({ + selected_model: '', + is_lasso_mode: false, + mode: GenerationModeEnum.Txt2Img, + rb_mode: ScriptMode.Txt2Img, + + batch_size: 1, + batch_count: 1, + steps: 20, + width: 512, + height: 512, + ratio: 1.0, + cfg: 7.0, + b_width_height_link: true, + denoising_strength: 0.7, + hr_denoising_strength: 0.7, + inpaint_full_res: false, + enable_hr: false, + sampler_name: 'Euler a', + image_cfg_scale: 1.5, + seed: '-1' as string, + mask_blur: 0, + mask_expansion: 0, + inpaint_full_res_padding: 0, + + hr_scale: 2.0, + + hr_resize_x: 512, + hr_resize_y: 512, + hr_second_pass_steps: 0, + restore_faces: false, + inpainting_fill: mask_content_config[0].value, + hr_upscaler: '', + + selection_mode: selection_mode_config[0].value, +}) +export const default_preset = { + sd_tab_preset: { + prompt: '', + negative_prompt: '', + // is_lasso_mode: false, + + batch_size: 1, + batch_count: 1, + steps: 20, + width: 512, + height: 512, + ratio: 1, + cfg: 7, + b_width_height_link: true, + denoising_strength: 0.7, + hr_denoising_strength: 0.7, + // inpaint_full_res: false, + // enable_hr: false, + sampler_name: 'Euler a', + image_cfg_scale: 1.5, + seed: '-1', + mask_blur: 0, + mask_expansion: 0, + inpaint_full_res_padding: 0, + hr_scale: 2, + hr_resize_x: 512, + hr_resize_y: 512, + hr_second_pass_steps: 0, + // restore_faces: false, + inpainting_fill: 0, + hr_upscaler: '', + selection_mode: 'ratio', + }, + controlnet_tab_preset: [{}, {}, {}, {}, {}, {}, {}], +} + +export const helper_store = new AStore({ + b_show_sampler: false, //false when off, true when on, + models: [] as any[], + loras: [] as any[], + sampler_list: [] as any[], + hr_upscaler_list: [] as string[], + previous_width: 512, + previous_height: 512, +}) +export async function refreshModels() { + let b_result = false + try { + g_models = await requestGetModels() + if (g_models.length > 0) { + b_result = true + } + + helper_store.data.models = g_models + + // for (let model of g_models) { + // // console.log(model.title)//Log + // // const menu_item_element = document.createElement('sp-menu-item') + // // menu_item_element.className = 'mModelMenuItem' + // menu_item_element.innerHTML = model.title + // menu_item_element.dataset.model_hash = model.hash + // menu_item_element.dataset.model_title = model.title + // // document + // // .getElementById('mModelsMenu') + // // .appendChild(menu_item_element) + // } + } catch (e) { + b_result = false + console.warn(e) + } + return b_result +} + +async function promptForUpdate(header_message: any, long_message: any) { + const shell = require('uxp').shell + + ;(async () => { + const buttons = ['Cancel', 'OK'] + const r1 = await dialog_box.prompt( + header_message, + long_message, + buttons + // 'Please Update you Plugin. it will take about 10 seconds to update', + // 'update from discord, update from github'[ + // ['Cancel', 'Discord', 'Github'] + // ('Cancel', 'OK') + // ] + ) + let url + try { + if (r1 === 'Cancel') { + /* cancelled or No */ + console.log('cancel') + } else if (r1 === 'Github') { + url = + 'https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin' + // await py_re.openUrlRequest(url) + } else if (r1 === 'Discord') { + console.log('Discord') + // url = 'https://discord.gg/3mVEtrddXJ' + // url = 'https://discord.gg/YkUJXYWK3c' + // await py_re.openUrlRequest(url) + } else if (r1 === 'Ok') { + } + // console.log('url: ', url) + } catch (e) { + console.warn(e, url) + } + })() +} +export async function updateClickEventHandler(current_version: string) { + try { + const online_data = await general.requestOnlineData() + const b_need_update = general.compareVersions( + current_version, + online_data.new_version + ) + + let header_message = "You're Plugin is up to date." + let long_message = '' + if (b_need_update) { + header_message = `New Version is Available (${online_data.new_version})` + long_message = online_data.update_message + } + + await promptForUpdate(header_message, long_message) + } catch (e) { + console.warn(e) + } +} + +export function tempDisableElement(element: any, time: number) { + element.classList.add('disableBtn') + element.disabled = true + // element.style.opacity = '0.65' + // element.style.cursor = 'not-allowed' + setTimeout(function () { + element.disabled = false + element.classList.remove('disableBtn') + // element.style.opacity = '1.0' + // element.style.cursor = 'default' + }, time) +} + +async function updateVersionUI() { + let bStatus = false + try { + const version = await getVersionRequest() + document.getElementById('lVersionNumber')!.textContent = version + if (version !== 'v0.0.0') { + bStatus = true + } + } catch (e) { + console.warn(e) + document.getElementById('lVersionNumber')!.textContent = 'v0.0.0' + bStatus = false + } + return bStatus +} + +//REFACTOR: move to generation_settings.js +export async function initSamplers() { + let bStatus = false + try { + // let sampler_group = document.getElementById('sampler_group')! + // sampler_group.innerHTML = '' + + let samplers = await requestGetSamplers() + if (!samplers) { + //if we failed to get the sampler list from auto1111, use the list stored in sampler.js + samplers = sampler_data.samplers + } + helper_store.data.sampler_list = samplers + + // for (let sampler of samplers) { + // // console.log(sampler)//Log + // // sampler.name + // // Euler + // // const rbSampler = document.createElement('sp-radio') + // // rbSampler.innerHTML = sampler.name + // // rbSampler.setAttribute('class', 'rbSampler') + // // rbSampler.setAttribute('value', sampler.name) + // // sampler_group.appendChild(rbSampler) + // //add click event on radio button for Sampler radio button, so that when a button is clicked it change g_sd_sampler globally + // } + // document + // .getElementsByClassName('rbSampler')[0] + // .setAttribute('checked', '') + if (samplers.length > 0) { + bStatus = true + } + } catch (e) { + console.warn(e) + } + return bStatus +} + +export async function refreshUI() { + try { + const b_proxy_server_status = await updateVersionUI() + if (b_proxy_server_status) { + html_manip.setProxyServerStatus('connected', 'disconnected') + // g_automatic_status = Enum.AutomaticStatusEnum['RunningWithApi'] + } else { + html_manip.setProxyServerStatus('disconnected', 'connected') + } + + //@ts-ignore + g_automatic_status = await checkAutoStatus() + //@ts-ignore + await displayNotification(g_automatic_status) + + const bSamplersStatus = await initSamplers() + + await refreshModels() + helper_store.data.loras = await requestLoraModels() + await refreshExtraUpscalers() + + await setInpaintMaskWeight(1.0) //set the inpaint conditional mask to 1 when the on plugin start + + //get the latest options + + await g_sd_options_obj.getOptions() + //get the selected model + store.data.selected_model = g_sd_options_obj.getCurrentModel() + //update the ui with that model title + + // const current_model_hash = + // html_manip.getModelHashByTitle(current_model_title) + // html_manip.autoFillInModel(current_model_hash) + + //fetch the inpaint mask weight from sd webui and update the slider with it. + const inpainting_mask_weight = + await g_sd_options_obj.getInpaintingMaskWeight() + console.log('inpainting_mask_weight: ', inpainting_mask_weight) + html_manip.autoFillInInpaintMaskWeight(inpainting_mask_weight) + + //init ControlNet Tab + + helper_store.data.hr_upscaler_list = await requestGetHiResUpscalers() + + g_controlnet_max_models = await control_net.requestControlNetMaxUnits() + await control_net.initializeControlNetTab(g_controlnet_max_models) + await main.populateVAE() + } catch (e) { + console.warn(e) + } +} + +export async function requestGetHiResUpscalers(): Promise { + try { + const full_url = `${g_sd_url}/sdapi/v1/upscalers` + let upscalers = await requestGet(full_url) + return [ + 'Latent', + 'Latent (antialiased)', + 'Latent (bicubic)', + 'Latent (bicubic antialiased)', + 'Latent (nearest)', + 'Latent (nearest-exact)', + ...upscalers.map((upscaler: any) => upscaler.name), + ] + } catch (e) { + console.warn('requestGetHiResUpscalers:', e) + return [ + 'Latent', + 'Latent (antialiased)', + 'Latent (bicubic)', + 'Latent (bicubic antialiased)', + 'Latent (nearest)', + 'Latent (nearest-exact)', + ] + } +} + +export async function requestLoraModels() { + const full_url = `${g_sd_url}/sdapi/v1/loras` + const lora_models = (await requestGet(full_url)) ?? [] + return lora_models +} + +export function getLoraModelPrompt(lora_model_name: string) { + return `` +} + +//add click event on radio button mode, so that when a button is clicked it change g_sd_mode globally +//REFACTOR: move to events.js +declare let g_sd_mode: string +export async function onModeChange(new_mode: ScriptMode) { + try { + g_sd_mode = new_mode + script_store.setMode(new_mode) + store.data.rb_mode = new_mode + store.data.mode = store.data.rb_mode as unknown as GenerationModeEnum + // console.log(`You clicked: ${g_sd_mode}`) + + //@ts-ignore + await postModeSelection() // do things after selection + } catch (e) { + console.warn(e) + } +} + +export function viewMaskExpansion() { + if (session_store.data.expanded_mask) { + const mask_src = general.base64ToBase64Url( + session_store.data.expanded_mask + ) + html_manip.setInitImageMaskSrc(mask_src) + } else { + console.log( + 'the mask has not been expanded, g_generation_session.base64maskExpansionImage is empty' + ) + } +} +function viewDrawnMask() { + //this is the generated mask or user drawn mask, but it's not the mask after expansion + if (session_store.data.mask) { + const mask_src = general.base64ToBase64Url(session_store.data.mask) + html_manip.setInitImageMaskSrc(mask_src) + } else { + console.log('no mask is available') + } +} +export function initInitMaskElement() { + //make init mask image use the thumbnail class with buttons + const mask_image_html = html_manip.getInitImageMaskElement() + const mask_parent_element = mask_image_html.parentElement + + const thumbnail_container = thumbnail.Thumbnail.wrapImgInContainer( + mask_image_html, + 'viewer-image-container' + ) + mask_parent_element.appendChild(thumbnail_container) + thumbnail.Thumbnail.addSPButtonToContainer( + thumbnail_container, + 'svg_sp_btn', + 'view original mask', + + viewDrawnMask, + null + ) + thumbnail.Thumbnail.addSPButtonToContainer( + thumbnail_container, + 'svg_sp_btn_expand', + 'view modified mask', + + viewMaskExpansion, + null + ) + // populateLoraModelMenu() // no need for await +} + +function scaleToRatio( + newValue1: number, + oldValue1: number, + newValue2: undefined, //get ignored + oldValue2: number, + maxValue: number, + minValue: number +) { + const ratio = newValue1 / oldValue1 + let finalNewValue2 = Math.max( + minValue, + Math.min(maxValue, oldValue2 * ratio) + ) + let finalNewValue1 = newValue1 + if (finalNewValue2 === maxValue || finalNewValue2 === minValue) { + finalNewValue1 = oldValue1 * (finalNewValue2 / oldValue2) + } + return [finalNewValue1, finalNewValue2] +} + +export function widthSliderOnChangeEventHandler( + new_value: number, + min_value: number, + max_value: number +) { + try { + const b_link = store.data.b_width_height_link + let final_width = new_value + let final_height + if (b_link) { + ;[final_width, final_height] = scaleToRatio( + new_value, + helper_store.data.previous_width, + undefined, + store.data.height, + max_value, + min_value + ) + + store.data.width = final_width + store.data.height = final_height + + helper_store.data.previous_width = store.data.width + helper_store.data.previous_height = store.data.height + } + } catch (e) { + console.error(e) + } +} + +export function heightSliderOnChangeEventHandler( + new_value: number, + min_value: number, + max_value: number +) { + try { + let new_height = new_value + const b_link = store.data.b_width_height_link + let final_height = new_height + let final_width + if (b_link) { + ;[final_height, final_width] = scaleToRatio( + new_height, + helper_store.data.previous_height, + undefined, + store.data.width, + max_value, + min_value + ) + + store.data.width = final_width + store.data.height = final_height + + helper_store.data.previous_width = store.data.width + helper_store.data.previous_height = store.data.height + } + } catch (e) { + console.error(e) + } +} +export function calcLinkedValue(new_value: number) {} +export async function initPlugin() { + try { + //*) load plugin settings + //*) load horde settings + //*) + //*) initialize the samplers + //*) + await settings_tab.loadSettings() + // await horde_native.HordeSettings.loadSettings() + const bSamplersStatus = await initSamplers() //initialize the sampler + await setInpaintMaskWeight(1.0) //set the inpaint conditional mask to 1 when the on plugin start + await refreshUI() + + //@ts-ignore + await loadPromptShortcut() + //@ts-ignore + await refreshPromptMenu() + } catch (e) { + console.error(e) + } +} +export function scaleFromToLabel(width: number, height: number, scale: number) { + const hr_width = Math.ceil(width * scale) + const hr_height = Math.ceil(height * scale) + return `${width}x${height} -> ${hr_width}x${hr_height}` +} + +export function onWidthSliderInput(new_value: number) { + try { + store.data.width = new_value + + store.data.ratio = calcRatio( + new_value, + store.data.height, + session_store.data.current_selection_info + ) + } catch (e) { + console.error(e) + } +} + +export function onHeightSliderInput(new_value: number) { + try { + store.data.height = new_value + store.data.ratio = calcRatio( + store.data.width, + new_value, + session_store.data.current_selection_info + ) + } catch (e) { + console.error(e) + } +} + +export function calcRatio( + width: number, + height: number, + selectionInfo: SelectionInfoType | undefined +) { + let ratio = 1 + + if (selectionInfo) { + ratio = (width * height) / (selectionInfo.width * selectionInfo.height) + } + return ratio +} + +export function loadPresetSettings(preset: any) { + if (preset?.sd_tab_preset) { + presetToStore(preset?.sd_tab_preset, store) + } + if (preset?.controlnet_tab_preset) { + preset?.controlnet_tab_preset.forEach( + (unit: controlNetUnitData, index: number) => { + try { + setUnitData(unit, index) + } catch (e) { + console.log('error at unit index: ', index) + console.error(e) + } + } + ) + // io_ts.presetToStore(preset?.controlnet_tab_preset, store) + } +} diff --git a/typescripts/session/generate.tsx b/typescripts/session/generate.tsx index a5faa30..57e1dc7 100644 --- a/typescripts/session/generate.tsx +++ b/typescripts/session/generate.tsx @@ -3,13 +3,24 @@ import ReactDOM from 'react-dom/client' import { observer } from 'mobx-react' -import { sd_tab_ts, session_ts, viewer } from '../entry' +// import { sd_tab_ts, session_ts, viewer } from '../entry' +import { store as session_store } from '../session/session_store' +import { Session } from '../session/session' +// import * as sd_tab_ts from '../sd_tab/sd_tab' +import { store as sd_tab_store } from '../sd_tab/util' +import * as viewer from '../viewer/viewer' + import './style/generate.css' import { io, note, psapi, selection } from '../util/oldSystem' import { GenerationModeEnum } from '../util/ts/enum' import { initializeBackground } from '../util/ts/document' import Locale from '../locale/locale' import { ErrorBoundary } from '../util/errorBoundary' +import { + store as viewer_store, + mask_store as viewer_mask_store, + // init_store as viewer_init_store, +} from '../viewer/viewer_util' declare let g_automatic_status: any declare let g_current_batch_index: number //example: take 'oI' in 'LassoInpaint' and replace it with 'o I' thus creating 'Lasso Inpaint' @@ -20,7 +31,7 @@ const modeDisplayNames = Object.fromEntries( ]) ) -const GenerateButtons = observer(() => { +export const GenerateButtons = observer(() => { return (
- {session_ts.store.data.can_generate ? ( + {session_store.data.can_generate ? (
) } @@ -194,3 +298,5 @@ root.render( ) + +progress_store.data.live_progress_image diff --git a/typescripts/stores.ts b/typescripts/stores.ts new file mode 100644 index 0000000..98d1086 --- /dev/null +++ b/typescripts/stores.ts @@ -0,0 +1,3 @@ +export { store as session_store } from './session/session_store' +export { store as sd_tab_store } from './sd_tab/util' +export { mask_store } from './viewer/viewer_util' diff --git a/typescripts/tool_bar/style/tool_bar.css b/typescripts/tool_bar/style/tool_bar.css new file mode 100644 index 0000000..ffb8506 --- /dev/null +++ b/typescripts/tool_bar/style/tool_bar.css @@ -0,0 +1,4 @@ +/* styles.css */ +#_tool_bar_container button:not(:last-child) { + margin-bottom: 3px; +} \ No newline at end of file diff --git a/typescripts/tool_bar/tool_bar.tsx b/typescripts/tool_bar/tool_bar.tsx new file mode 100644 index 0000000..5415d56 --- /dev/null +++ b/typescripts/tool_bar/tool_bar.tsx @@ -0,0 +1,220 @@ +import { observer } from 'mobx-react' +import React from 'react' +import ReactDOM from 'react-dom/client' + +import { general, html_manip, io, psapi } from '../util/oldSystem' +import { + default_preset, + loadPresetSettings, + store as sd_tab_store, +} from '../sd_tab/util' +import { requestPost } from '../util/ts/api' +import ControlNetStore from '../controlnet/store' +import { AStore } from '../main/astore' + +import { ErrorBoundary } from '../util/errorBoundary' +import './style/tool_bar.css' +import { presetToStore } from '../util/ts/io' +import { multiPrompts } from '../entry' +import { activateSessionSelectionArea } from '../util/ts/selection' +declare let g_sd_url: string + +export const store = new AStore({ + at_controlnet_unit_index: 0, +}) +async function clipInterrogate() { + try { + const width = sd_tab_store.data.width + const height = sd_tab_store.data.height + const selectionInfo = await psapi.getSelectionInfoExe() + + const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New( + width, + height, + selectionInfo, + true + ) + + const url = `${g_sd_url}/sdapi/v1/interrogate` + + const payload = { + image: base64, + model: 'clip', + } + const result_json = await requestPost(url, payload) + console.log(result_json) + return result_json + } catch (e) { + console.warn(e) + } +} + +async function onInterrogate(evt: any) { + // start sudo timer after 1 seconds delay + let sudo_timer_id + setTimeout(() => { + sudo_timer_id = general.sudoTimer('Interrogate') + }, 1000) + const interrogate_result = await clipInterrogate() + + if (interrogate_result.caption) { + html_manip.autoFillInPrompt(interrogate_result.caption) + } + + // after the clipInterrogate finish stop the timer + + html_manip.updateProgressBarsHtml(0, 'No work in progress') + clearInterval(sudo_timer_id) + sudo_timer_id = null +} + +function scrollToPreview() { + try { + document + .querySelector('#search_second_panel > div.previewContainer')! + .scrollIntoView() + // document.getElementById('taPrompt').scrollIntoView() + } catch (e) { + console.error(e) + } +} +@observer +class ToolBar extends React.Component<{}> { + componentDidMount(): void { + console.log('ToolBar did mount') + } + render() { + return ( +
+ + + + + + +
+ +
+
+ ) + } +} + +const container = document.getElementById('toolBarContainer')! +const root = ReactDOM.createRoot(container) + +root.render( + + + + + +) diff --git a/typescripts/util/collapsible.tsx b/typescripts/util/collapsible.tsx new file mode 100644 index 0000000..2f58c5b --- /dev/null +++ b/typescripts/util/collapsible.tsx @@ -0,0 +1,69 @@ +import React, { CSSProperties, ComponentType } from 'react' +// import ReactDOM from 'react-dom' + +import { useState, ReactNode } from 'react' +import Locale from '../locale/locale' +interface CollapsibleProps { + label: string + labelStyle?: React.CSSProperties + containerStyle?: React.CSSProperties + defaultIsOpen?: boolean + checked?: boolean + checkboxCallback?: (checked: boolean) => void + children: ReactNode +} + +export function Collapsible({ + label, + labelStyle, + containerStyle, + defaultIsOpen = false, + checkboxCallback, + checked, + children, +}: CollapsibleProps) { + const [isOpen, setIsOpen] = useState(defaultIsOpen) + + const handleToggle = () => { + setIsOpen(!isOpen) + } + + return ( + /*useObserver(()=>*/
+
+ + {label} + + + + {checkboxCallback && checked !== void 0 ? ( + { + event.stopPropagation() + }} + onChange={(event: any) => { + checkboxCallback(event.target.checked) + }} + checked={checked} + /> + ) : ( + void 0 + )} + + {isOpen ? '∨' : '<'} + +
+ {/* {isOpen &&
{children}
} */} +
{children}
+
+ ) +} diff --git a/typescripts/util/elements.tsx b/typescripts/util/elements.tsx index 040ea24..96ae38d 100644 --- a/typescripts/util/elements.tsx +++ b/typescripts/util/elements.tsx @@ -200,6 +200,7 @@ export class SpMenu extends React.Component<{ label_item?: string onChange?: any selected_index?: number + size?: string }> { state = { selectedItem: this.props.items ? this.props.items[0] : undefined, @@ -232,49 +233,48 @@ export class SpMenu extends React.Component<{ render() { return ( -
- - - {this.props.label_item && ( - - {this.props.label_item} - - )} - {this.props.items?.map((item, index: number) => ( - { - this.handleItemClick(item, index) - }} - > - {item} - - ))} - - -
+ + + {this.props.label_item && ( + + {this.props.label_item} + + )} + {this.props.items?.map((item, index: number) => ( + { + this.handleItemClick(item, index) + }} + > + {item} + + ))} + + ) } } @@ -392,6 +392,17 @@ export class SpSlider extends PhotoshopElem { ) } } +export class SpTextfield extends PhotoshopElem { + render() { + const [attr] = this.splitProps(this.props) + return ( + (this.elem = elem)} + {...attr} + > + ) + } +} export class SpRadioGroup extends PhotoshopElem { render() { const [attr] = this.splitProps(this.props) diff --git a/typescripts/util/oldSystem.tsx b/typescripts/util/oldSystem.tsx index 9b1417b..b7e9780 100644 --- a/typescripts/util/oldSystem.tsx +++ b/typescripts/util/oldSystem.tsx @@ -7,7 +7,7 @@ const req = window['require'] const selection = req('./selection') const note = req('./utility/notification') const controlnet_preset = req('./utility/presets/controlnet_preset') -const preset = req('./utility/presets/preset') + const Enum = req('./enum') const api = req('./utility/api') const python_replacement = req('./utility/sdapi/python_replacement') @@ -19,7 +19,10 @@ const io = req('./utility/io') const settings_tab = req('./utility/tab/settings') const layer_util = req('./utility/layer') const session = req('./utility/session') +const dialog_box = req('./dialog_box') +const sampler_data = req('./utility/sampler') +const thumbnail = req('./thumbnail') interface _Jimp extends Jimp {} const _Jimp: typeof Jimp = (window as any)['Jimp'] @@ -27,7 +30,6 @@ export { selection, note, controlnet_preset, - preset, Enum, api, python_replacement, @@ -39,5 +41,8 @@ export { settings_tab, layer_util, session, + dialog_box, + sampler_data, + thumbnail, _Jimp as Jimp, } diff --git a/typescripts/util/ts/enum.ts b/typescripts/util/ts/enum.ts index 8e58ddb..c450729 100644 --- a/typescripts/util/ts/enum.ts +++ b/typescripts/util/ts/enum.ts @@ -8,6 +8,13 @@ export enum GenerationModeEnum { LassoOutpaint = 'lasso_outpaint', } +export enum ScriptMode { + Txt2Img = 'txt2img', + Img2Img = 'img2img', + Inpaint = 'inpaint', + Outpaint = 'outpaint', +} + export enum MaskModeEnum { Transparent = 'transparent', Borders = 'border', @@ -22,3 +29,8 @@ export interface SelectionInfoType { width: number height: number } + +export enum PresetTypeEnum { + SDPreset = 'sd_preset', + ControlNetPreset = 'controlnet_preset', +} diff --git a/typescripts/util/ts/io.ts b/typescripts/util/ts/io.ts index c60148c..7b82fd0 100644 --- a/typescripts/util/ts/io.ts +++ b/typescripts/util/ts/io.ts @@ -3,7 +3,10 @@ import { Jimp, io, psapi } from '../oldSystem' import { base64ToFileAndGetLayer } from './document' import { transformCurrentLayerTo } from './layer' import { Layer } from 'photoshop/dom/Layer' +import { lstatSync, readFileSync, writeFileSync } from 'fs' +import { AStore } from '../../main/astore' const executeAsModal = core.executeAsModal +type KeyValuePair = { [key: string]: any } //REFACTOR: move to psapi.js export function _arrayBufferToBase64(buffer: any) { @@ -139,3 +142,31 @@ async function getBase64FromJimp(jimp_image: Jimp) { const base64 = dataURL.replace(/^data:image\/png;base64,/, '') return base64 } + +export function readPreset(path: string) { + try { + const content = readFileSync(path, 'utf-8') + JSON.parse(content) + } catch (e) { + console.error(e) + } +} + +export function writePreset(path: string, preset: KeyValuePair) { + try { + writeFileSync(path, JSON.stringify(preset)) + } catch (e) { + console.error(e) + } +} + +export function storeToPreset(store: any) { + return store.toJsFunc().data +} + +export function presetToStore(preset: KeyValuePair, store: any) { + store.data = { + ...store.data, + ...preset, + } +} diff --git a/typescripts/util/ts/layer.ts b/typescripts/util/ts/layer.ts index 1960af8..460af9c 100644 --- a/typescripts/util/ts/layer.ts +++ b/typescripts/util/ts/layer.ts @@ -1,6 +1,7 @@ import { app, core, action } from 'photoshop' import { layer_util, psapi } from '../oldSystem' -import { settings_tab_ts } from '../../entry' +// import { settings_tab_ts } from '../../entry' +import * as settings_tab_ts from '../../settings/settings' const executeAsModal = core.executeAsModal const { batchPlay } = action diff --git a/typescripts/util/ts/sdapi.ts b/typescripts/util/ts/sdapi.ts new file mode 100644 index 0000000..c4dd295 --- /dev/null +++ b/typescripts/util/ts/sdapi.ts @@ -0,0 +1,96 @@ +declare let g_version: any +declare let g_sd_url: any + +export async function getVersionRequest() { + console.log('requestGetSamplers: ') + const current_version = g_version + + return current_version +} +export async function requestGetSamplers() { + let json = null + try { + console.log('requestGetSamplers: ') + + const full_url = `${g_sd_url}/sdapi/v1/samplers` + let request = await fetch(full_url) + json = await request.json() + // console.log('samplers json:', json) + } catch (e) { + console.warn(e) + } + return json +} + +export async function requestGetUpscalers() { + console.log('requestGetUpscalers: ') + let json = [] + const full_url = `${g_sd_url}/sdapi/v1/upscalers` + try { + let request = await fetch(full_url) + json = await request.json() + console.log('upscalers json:') + console.dir(json) + } catch (e) { + console.warn(`issues requesting from ${full_url}`, e) + } + return json +} + +export async function setInpaintMaskWeight(value: number) { + const full_url = `${g_sd_url}/sdapi/v1/options` + try { + const payload = { + inpainting_mask_weight: value, + } + await fetch(full_url, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload), + }) + } catch (e) { + console.warn(e) + } +} + +export async function requestGetModels() { + console.log('requestGetModels: ') + let json = [] + const full_url = `${g_sd_url}/sdapi/v1/sd-models` + try { + let request = await fetch(full_url) + json = await request.json() + console.log('models json:') + console.dir(json) + } catch (e) { + console.warn(`issues requesting from ${full_url}`, e) + } + return json +} + +export async function requestSwapModel(model_title: string) { + console.log('requestSwapModel: ') + + const full_url = `${g_sd_url}/sdapi/v1/options` + const payload = { + sd_model_checkpoint: model_title, + } + let request = await fetch(full_url, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload), + }) + + let json = await request.json() + + console.log('models json:') + console.dir(json) + + return json +} diff --git a/typescripts/util/ts/selection.ts b/typescripts/util/ts/selection.ts index 6f61530..541f1f7 100644 --- a/typescripts/util/ts/selection.ts +++ b/typescripts/util/ts/selection.ts @@ -1,9 +1,9 @@ import { moveImageToLayer, moveImageToLayer_old } from './io' -import { io, layer_util } from '../oldSystem' -import { session_ts } from '../../entry' +import { io, layer_util, psapi } from '../oldSystem' import { action, core } from 'photoshop' import { MaskModeEnum } from './enum' +import { session_store } from '../../stores' const executeAsModal = core.executeAsModal const batchPlay = action.batchPlay @@ -11,7 +11,8 @@ export async function applyMaskFromBlackAndWhiteImage( black_and_white_base64: string, layer_id: any, selectionInfo: any, - b_borders_or_corners: MaskModeEnum = MaskModeEnum.Transparent + b_borders_or_corners: MaskModeEnum = MaskModeEnum.Transparent, + expand_by = 10 ) { let mask_layer try { @@ -50,7 +51,7 @@ export async function applyMaskFromBlackAndWhiteImage( _obj: 'expand', by: { _unit: 'pixelsUnit', - _value: 10, + _value: expand_by, }, selectionModifyEffectAtCanvasBounds: true, _isCommand: true, @@ -156,3 +157,15 @@ export async function selectionFromBlackAndWhiteImage( await layer_util.deleteLayers([mask_layer]) } } + +export async function activateSessionSelectionArea() { + try { + if (psapi.isSelectionValid(session_store.data.selectionInfo)) { + await psapi.reSelectMarqueeExe(session_store.data.selectionInfo) + //@ts-ignore + await eventHandler() + } + } catch (e) { + console.warn(e) + } +} diff --git a/typescripts/util/ts/ui_ts.ts b/typescripts/util/ts/ui_ts.ts new file mode 100644 index 0000000..a5369d5 --- /dev/null +++ b/typescripts/util/ts/ui_ts.ts @@ -0,0 +1,433 @@ +import { multiPrompts } from '../../entry' +import { + getAllCustomPresetsSettings, + loadCustomPreset, + loadPreset, +} from '../../preset/shared_ui_preset' +import { sd_tab_store } from '../../stores' +import { html_manip } from '../oldSystem' +import { PresetTypeEnum, ScriptMode } from './enum' + +let LatentNoiseSettings = { + model: null, + prompt_shortcut: null, + positive_prompt: null, + negative_prompt: null, + generation_mode: null, + batch_size: null, + steps: null, + width: null, + height: null, + firstphase_width: null, + firstphase_height: null, + cfg: null, + denoising_strength: 0.92, + hi_res_denoising_strength: null, + mask_blur: null, + inpaint_at_full_res: null, + hi_res_fix: null, + inpaint_padding: null, + seed: null, + samplers: null, + mask_content: '2', +} + +let FillSettings = { + model: null, + prompt_shortcut: null, + positive_prompt: null, + negative_prompt: null, + generation_mode: null, + batch_size: null, + steps: null, + width: null, + height: null, + firstphase_width: null, + firstphase_height: null, + cfg: null, + denoising_strength: 0.7, + hi_res_denoising_strength: null, + mask_blur: null, + inpaint_at_full_res: null, + hi_res_fix: null, + inpaint_padding: null, + seed: null, + samplers: null, + mask_content: '0', +} +let OriginalSettings = { + model: null, + prompt_shortcut: null, + positive_prompt: null, + negative_prompt: null, + generation_mode: null, + batch_size: null, + steps: null, + width: null, + height: null, + firstphase_width: null, + firstphase_height: null, + cfg: null, + denoising_strength: 0.7, + hi_res_denoising_strength: null, + mask_blur: null, + inpaint_at_full_res: null, + hi_res_fix: null, + inpaint_padding: null, + seed: null, + samplers: null, + mask_content: '1', +} +let HealBrushSettings = { + model: null, + prompt_shortcut: null, + positive_prompt: null, + negative_prompt: null, + generation_mode: null, + batch_size: null, + steps: '25', + width: null, + height: null, + firstphase_width: null, + firstphase_height: null, + cfg: '9', + denoising_strength: 0.92, + hi_res_denoising_strength: null, + mask_blur: 1, + inpaint_at_full_res: null, + hi_res_fix: null, + inpaint_padding: null, + seed: null, + samplers: null, + mask_content: '2', + mask_expansion: 2, +} + +class UI { + constructor() {} +} +interface UIElements { + [key: string]: UIElement + + prompt: UIElement + negative_prompt: UIElement + mode: UIElement + batch_size: UIElement + batch_count: UIElement + + steps: UIElement + width: UIElement + height: UIElement + + cfg: UIElement + denoising_strength: UIElement + mask_content: UIElement + seed: UIElement + mask_blur: UIElement + mask_expansion: UIElement + samplers: UIElement +} +class UIElement { + name: any + html_elem: any + sd_value: any + constructor() { + this.name + this.html_elem + this.sd_value + } + setValue(new_value: any) {} + getValue(): any {} +} +function createUIElement(getter: any, setter: any) { + let ui_element_obj = new UIElement() + ui_element_obj.getValue = getter + ui_element_obj.setValue = setter + return ui_element_obj +} +class UISettings { + prompt: UIElement + negative_prompt: UIElement + mode: UIElement + steps: UIElement + batch_size: UIElement + batch_count: UIElement + width: UIElement + height: UIElement + cfg: UIElement + denoising_strength: UIElement + mask_content: UIElement + seed: UIElement + mask_blur: UIElement + mask_expansion: UIElement + samplers: UIElement + uiElements: UIElements + // get and set the settings of the ui. the stable diffusion settings not the human friendly settings + constructor() { + const createUIElementWrapper = ( + getter: () => T, + setter: (value: T) => void + ) => { + return createUIElement(getter, setter) + } + + const sdTabStoreDataWrapper = ( + key: keyof typeof sd_tab_store.data + ) => { + return createUIElementWrapper( + () => sd_tab_store.data[key] as T, + (value: T) => (sd_tab_store.data[key] = value) + ) + } + this.prompt = createUIElement( + () => { + return multiPrompts.getPrompt().positive + }, + (value: string) => { + multiPrompts.setPrompt({ positive: value }) + } + ) + this.negative_prompt = createUIElement( + () => { + return multiPrompts.getPrompt().negative + }, + (value: string) => { + multiPrompts.setPrompt({ negative: value }) + } + ) + + this.mode = sdTabStoreDataWrapper('rb_mode') + this.batch_size = sdTabStoreDataWrapper('batch_size') + this.batch_count = sdTabStoreDataWrapper('batch_count') + this.steps = sdTabStoreDataWrapper('steps') + this.width = sdTabStoreDataWrapper('width') + this.height = sdTabStoreDataWrapper('height') + this.cfg = sdTabStoreDataWrapper('cfg') + // this.mask_blur = + + this.denoising_strength = createUIElement( + () => { + return sd_tab_store.data.denoising_strength + }, + (value: number) => { + sd_tab_store.data.denoising_strength = value + } + ) + + this.mask_content = createUIElement( + html_manip.getMaskContent, + html_manip.setMaskContent + ) + this.seed = createUIElement( + () => { + return sd_tab_store.data.seed + }, + (value: string) => { + sd_tab_store.data.seed = value + } + ) + + this.mask_blur = createUIElement( + () => { + return sd_tab_store.data.mask_blur + }, + (value: number) => { + sd_tab_store.data.mask_blur = value + } + ) + + this.mask_expansion = createUIElement( + html_manip.getMaskExpansion, + html_manip.setMaskExpansion + ) + this.samplers = createUIElement( + () => { + return sd_tab_store.data.sampler_name + }, + (value: string) => { + sd_tab_store.data.sampler_name = value + } + ) + + this.uiElements = { + // model: null, + // prompt_shortcut: null, + prompt: this.prompt, + negative_prompt: this.negative_prompt, + // selection_mode: null, + mode: this.mode, + batch_size: this.batch_size, + batch_count: this.batch_count, + steps: this.steps, + width: this.width, + height: this.height, + + cfg_scale: this.cfg, + denoising_strength: this.denoising_strength, + // hi_res_denoising_strength:0.7, + mask_blur: this.mask_blur, + mask_expansion: this.mask_expansion, + // inpaint_at_full_res: false, + // hi_res_fix:false, + // inpaint_padding:0, + seed: this.seed, + sampler_index: this.samplers, + mask_content: this.mask_content, + cfg: this.cfg, + samplers: this.samplers, + } + } + + autoFillInSettings(settings: any) { + for (const [name, value] of Object.entries(settings)) { + if (this.uiElements.hasOwnProperty(name) && value) { + //get the values for debugging + const old_value = this.uiElements[name].getValue() + console.log( + '(name,old_value) => newValue:', + name, + old_value, + value + ) + //set the value + this.uiElements[name].setValue(value) + } + } + } + getSettings() { + let settings: any = {} + for (const [name, ui_element] of Object.entries(this.uiElements)) { + if (ui_element) { + const value = ui_element.getValue() + settings[name] = value + } + } + return settings + } + + saveAsJson(json_file_name: string, settings: any) { + for (const [name, value] of Object.entries(settings)) { + if (this.uiElements.hasOwnProperty(name) && value) { + //get the values for debugging + const old_value = this.uiElements[name].getValue() + console.log( + '(name,old_value) => newValue:', + name, + old_value, + value + ) + + //set the value + } + } + } +} +// const ui_settings = new UISettings() + +function loadLatentNoiseSettings(ui_settings: any) { + loadPreset(ui_settings, LatentNoiseSettings) +} + +function loadFillSettings(ui_settings: any) { + loadPreset(ui_settings, FillSettings) +} +function loadOriginalSettings(ui_settings: any) { + loadPreset(ui_settings, OriginalSettings) +} +async function loadHealBrushSettings(ui_settings: any) { + document.getElementById('rbModeInpaint')!.click() + + loadPreset(ui_settings, HealBrushSettings) +} + +function loadCustomPresetsSettings() {} +async function mapCustomPresetsToLoaders(ui_settings_obj: any) { + const name_to_settings_obj = await getAllCustomPresetsSettings() + const preset_name_to_loader_obj: any = {} + for (const [preset_name, preset_settings] of Object.entries( + name_to_settings_obj + )) { + preset_name_to_loader_obj[preset_name] = () => { + loadCustomPreset(ui_settings_obj, preset_settings) + } + } + return preset_name_to_loader_obj +} + +const g_nativePresets = { + fill: loadFillSettings, + original: loadOriginalSettings, + 'latent noise': loadLatentNoiseSettings, + 'Heal Brush': loadHealBrushSettings, +} +export function getNativeSDPresets() { + return g_nativePresets +} +let g_ui_settings_object = new UISettings() +function getUISettingsObject() { + return g_ui_settings_object +} + +//REFACTOR: move to ui.js +function addPresetMenuItem(preset_title: string) { + // console.log(model_title,model_name) + const menu_item_element = document.createElement('sp-menu-item') + menu_item_element.className = 'mPresetMenuItem' + menu_item_element.innerHTML = preset_title + + // menu_item_element.addEventListener('select',()=>{ + // preset_func(g_ui_settings) + // }) + return menu_item_element +} +//REFACTOR: move to ui.js +// async function populatePresetMenu() { +// document.getElementById('mPresetMenu')!.innerHTML = '' +// const divider_elem = document.createElement('sp-menu-divider') +// const preset_name = 'Select Smart Preset' +// // const preset_func = () => {} +// const dummy_preset_item = addPresetMenuItem(preset_name) +// dummy_preset_item.setAttribute('selected', 'selected') +// // dummy_preset_item.setAttribute('disabled') +// document.getElementById('mPresetMenu')!.appendChild(dummy_preset_item) +// document.getElementById('mPresetMenu')!.appendChild(divider_elem) +// const presets = await getLoadedPresets(g_ui_settings_object) +// for (const [key, value] of Object.entries(presets)) { +// const preset_menu_item = addPresetMenuItem(key) +// document.getElementById('mPresetMenu')!.appendChild(preset_menu_item) +// } +// } + +// populatePresetMenu() +//REFACTOR: move to preset_tab.js +// document +// .getElementById('mPresetMenu')! +// .addEventListener('change', async (evt: any) => { +// const preset_index = evt.target.selectedIndex +// const preset_name: string = evt.target.options[preset_index].textContent +// const presets: any = await getLoadedPresets(g_ui_settings_object) +// if (presets.hasOwnProperty(preset_name)) { +// const loader = presets[preset_name] +// if (loader.constructor.name === 'AsyncFunction') { +// await loader(g_ui_settings_object) +// } else { +// loader(g_ui_settings_object) +// } +// } +// }) + +// { +// sd_tab: +// controlnet_tab: +// settings_tab: +// } +export { + UI, + UIElement, + UISettings, + loadLatentNoiseSettings, + loadFillSettings, + loadHealBrushSettings, + getUISettingsObject, + // populatePresetMenu, +} diff --git a/typescripts/viewer/preview.tsx b/typescripts/viewer/preview.tsx index c53efbb..071ae6e 100644 --- a/typescripts/viewer/preview.tsx +++ b/typescripts/viewer/preview.tsx @@ -1,10 +1,12 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import Collapsible from '../after_detailer/after_detailer' +import { Collapsible } from '../util/collapsible' import { observer } from 'mobx-react' import { AStore } from '../main/astore' -import { progress } from '../entry' +// import { progress } from '../entry' +import * as progress from '../session/progress' + import './style/preview.css' import { reaction } from 'mobx' import Locale from '../locale/locale' diff --git a/typescripts/viewer/viewer.tsx b/typescripts/viewer/viewer.tsx index a3ba5b0..a4baaa5 100644 --- a/typescripts/viewer/viewer.tsx +++ b/typescripts/viewer/viewer.tsx @@ -16,8 +16,13 @@ import { moveImageToLayer_old, } from '../util/ts/io' import { io, layer_util, psapi, selection } from '../util/oldSystem' -import Collapsible from '../after_detailer/after_detailer' -import { progress, session_ts, settings_tab_ts } from '../entry' +import { Collapsible } from '../util/collapsible' +// import { progress } from '../entry' + +import * as progress from '../session/progress' +import * as settings_tab_ts from '../settings/settings' + +import { store as session_store } from '../session/session_store' import { reaction } from 'mobx' import { GenerationModeEnum, @@ -29,27 +34,19 @@ import { action, app, core } from 'photoshop' import Locale from '../locale/locale' import { applyMaskFromBlackAndWhiteImage } from '../util/ts/selection' import { ErrorBoundary } from '../util/errorBoundary' +import { Session } from '../session/session' +import { + ClassNameEnum, + ClickTypeEnum, + init_store, + mask_store, + store, +} from './viewer_util' const executeAsModal = core.executeAsModal const batchPlay = action.batchPlay declare let g_generation_session: any -enum ClickTypeEnum { - Click = 'click', - ShiftClick = 'shift_click', - AltClick = 'alt_click', - SecondClick = 'second_click', //when we click a thumbnail that is active/ has orange border -} - -enum OutputImageStateEnum { - Add = 'add', - remove = 'remove', -} -enum ClassNameEnum { - Green = 'viewerImgSelected', - Orange = 'viewerImgActive', - None = '', -} function findClickType(event: any) { let click_type: ClickTypeEnum = ClickTypeEnum.Click @@ -61,46 +58,6 @@ function findClickType(event: any) { return click_type } -interface AStoreData { - images: string[] - thumbnails: string[] - metadata: any[] // metadata for each image - width: number - height: number - - prev_layer: any - clicked_index: number | undefined - - permanent_indices: number[] - - prev_index: number - is_stored: boolean[] - layers: any[] - class_name: ClassNameEnum[] - can_click: boolean - auto_mask: boolean -} -export const store = new AStore({ - images: [], - thumbnails: [], - metadata: [], // metadata for each image - width: 50, - height: 50, - - prev_layer: null, - clicked_index: undefined, - - permanent_indices: [], - - prev_index: -1, - - is_stored: [], - layers: [], - class_name: [], - can_click: true, - auto_mask: true, -}) - const timer = (ms: any) => new Promise((res) => setTimeout(res, ms)) //when a generation is done, add the last generated image from the viewer to tha canvas reaction( @@ -134,71 +91,7 @@ reaction( } } ) -export const init_store = new AStore({ - images: [], - thumbnails: [], - width: 50, - height: 50, - - prev_layer: null, - clicked_index: null, - - permanent_indices: [], - - prev_index: -1, - output_image_obj_list: [], - is_stored: [], - layers: [], - class_name: [], - can_click: true, -}) -export const mask_store = new AStore({ - images: [], - thumbnails: [], - output_images_masks: [], - - width: 50, - height: 50, - - prev_layer: null, - clicked_index: null, - - permanent_indices: [], - - prev_index: -1, - output_image_obj_list: [], - is_stored: [], - layers: [], - class_name: [], - can_click: true, -}) - -interface AStoreDataWithImagesAndThumbnails { - images: string[] - thumbnails: string[] -} - -export async function updateViewerStoreImageAndThumbnail< - T extends AStoreDataWithImagesAndThumbnails ->(store: AStore, images: string[]) { - try { - if (typeof images === 'undefined' || !images) { - return null - } - store.data.images = images - const thumbnail_list = [] - for (const base64 of images) { - const thumbnail = await io.createThumbnail(base64, 300) - thumbnail_list.push(thumbnail) - } - - store.data.thumbnails = thumbnail_list - } catch (e) { - console.warn(e) - console.warn('images: ', images) - } -} const add_new = async ( base64: string, mask?: string, @@ -239,7 +132,8 @@ const add_new = async ( await selection.black_white_layer_to_mask_multi_batchplay( mask_layer.id, layer.id, - 'mask' + 'mask', + mask_store.data.expand_by ) await layer_util.deleteLayers([mask_layer]) } else { @@ -249,7 +143,8 @@ const add_new = async ( channel_mask_monochrome.base64, layer.id, selectionInfo, - settings_tab_ts.store.data.b_borders_or_corners + settings_tab_ts.store.data.b_borders_or_corners, + mask_store.data.expand_by ) } } @@ -276,12 +171,12 @@ const add = async ( store.data.auto_mask ) { // const base64_monochrome_mask = await io.convertGrayscaleToMonochrome( - // session_ts.store.data.selected_mask + // session_store.data.selected_mask // ) const timer = (ms: any) => new Promise((res) => setTimeout(res, ms)) const mask_monochrome = await io.convertGrayscaleToMonochrome( - // session_ts.store.data.expanded_mask + // session_store.data.expanded_mask mask ) const channel_mask = mask_monochrome @@ -292,7 +187,8 @@ const add = async ( channel_mask, layer.id, selectionInfo, - settings_tab_ts.store.data.b_borders_or_corners + settings_tab_ts.store.data.b_borders_or_corners, + mask_store.data.expand_by ) } @@ -339,21 +235,6 @@ const remove = async (layer: any) => { await layer_util.deleteLayers([layer]) // delete previous layer } -export const resetViewer = () => { - store.updateProperty('images', []) - store.data.thumbnails = [] - store.data.prev_index = -1 - store.data.is_stored = [] - store.data.layers = [] - store.data.class_name = [] - store.data.can_click = true - - mask_store.data.images = [] - mask_store.data.thumbnails = [] - init_store.data.images = [] - init_store.data.thumbnails = [] -} - const addAll = async () => { let i = 0 for (let i = 0; i < store.data.images.length; i++) { @@ -366,22 +247,22 @@ const addAll = async () => { await addWithHistory( store.data.images[i], mask_store.data?.output_images_masks?.[i] ?? void 0, - session_ts.store.data.selectionInfo, - session_ts.store.data.mode + session_store.data.selectionInfo, + session_store.data.mode ) } - session_ts.Session.endSession() + Session.endSession() } const discardAll = async () => { for (let i = 0; i < store.data.images.length; i++) { await remove(store.data.layers[i]) } - session_ts.Session.endSession() + Session.endSession() } const onlySelected = () => { - session_ts.Session.endSession() + Session.endSession() } export const handleOutputImageThumbnailClick = async ( index: number, @@ -423,8 +304,8 @@ export const handleOutputImageThumbnailClick = async ( const layer = await addWithHistory( image, mask_store.data?.output_images_masks?.[index] ?? void 0, - session_ts.store.data.selectionInfo, - session_ts.store.data.mode + session_store.data.selectionInfo, + session_store.data.mode ) await remove(store.data.layers[index]) console.log('layer:', layer) @@ -458,8 +339,8 @@ export const handleOutputImageThumbnailClick = async ( const layer = await addWithHistory( image, mask_store.data?.output_images_masks?.[index] ?? void 0, - session_ts.store.data.selectionInfo, - session_ts.store.data.mode + session_store.data.selectionInfo, + session_store.data.mode ) await remove(store.data.layers[index]) store.data.layers[index] = layer @@ -512,7 +393,7 @@ export const handleOutputImageThumbnailClick = async ( const Viewer = observer(() => { // console.log('rendered', store.toJsFunc()) const display_button: Boolean = - session_ts.store.data.is_active && session_ts.store.data.can_generate + session_store.data.is_active && session_store.data.can_generate const button_style = { display: display_button ? 'block' : 'none', marginRight: '3px', @@ -585,7 +466,7 @@ const Viewer = observer(() => { GenerationModeEnum.Inpaint, GenerationModeEnum.LassoInpaint, GenerationModeEnum.Outpaint, - ].includes(session_ts.store.data.mode) + ].includes(session_store.data.mode) ? void 0 : 'none', marginRight: '10px', @@ -600,6 +481,21 @@ const Viewer = observer(() => { Locale('Apply Auto Masking') } + { + mask_store.data.expand_by = evt.target.value + }} + title="expand the Photoshop masking by x pixels" + > + {Locale('Expand by')} + + {mask_store.data.expand_by} + +
{ callback: async (index: number) => { await moveImageToLayer( mask_store.data.images[index], - session_ts.store.data.selectionInfo, + session_store.data.selectionInfo, 'mask' ) }, @@ -675,7 +571,7 @@ const Viewer = observer(() => { const ToolbarViewerButtons = observer(() => { const display_button: Boolean = - session_ts.store.data.is_active && session_ts.store.data.can_generate + session_store.data.is_active && session_store.data.can_generate const button_style = { display: display_button ? 'block' : 'none', diff --git a/typescripts/viewer/viewer_util.ts b/typescripts/viewer/viewer_util.ts new file mode 100644 index 0000000..4800a8e --- /dev/null +++ b/typescripts/viewer/viewer_util.ts @@ -0,0 +1,138 @@ +import { AStore } from '../main/astore' +import { io } from '../util/oldSystem' + +export enum ClickTypeEnum { + Click = 'click', + ShiftClick = 'shift_click', + AltClick = 'alt_click', + SecondClick = 'second_click', //when we click a thumbnail that is active/ has orange border +} + +export enum OutputImageStateEnum { + Add = 'add', + remove = 'remove', +} +export enum ClassNameEnum { + Green = 'viewerImgSelected', + Orange = 'viewerImgActive', + None = '', +} +interface AStoreData { + images: string[] + thumbnails: string[] + metadata: any[] // metadata for each image + width: number + height: number + + prev_layer: any + clicked_index: number | undefined + + permanent_indices: number[] + + prev_index: number + is_stored: boolean[] + layers: any[] + class_name: ClassNameEnum[] + can_click: boolean + auto_mask: boolean +} +export const store = new AStore({ + images: [], + thumbnails: [], + metadata: [], // metadata for each image + width: 50, + height: 50, + + prev_layer: null, + clicked_index: undefined, + + permanent_indices: [], + + prev_index: -1, + + is_stored: [], + layers: [], + class_name: [], + can_click: true, + auto_mask: true, +}) +export const init_store = new AStore({ + images: [], + thumbnails: [], + + width: 50, + height: 50, + + prev_layer: null, + clicked_index: null, + + permanent_indices: [], + + prev_index: -1, + output_image_obj_list: [], + is_stored: [], + layers: [], + class_name: [], + can_click: true, +}) +export const mask_store = new AStore({ + images: [], + thumbnails: [], + output_images_masks: [], + + width: 50, + height: 50, + expand_by: 0, + prev_layer: null, + clicked_index: null, + + permanent_indices: [], + + prev_index: -1, + output_image_obj_list: [], + is_stored: [], + layers: [], + class_name: [], + can_click: true, +}) + +interface AStoreDataWithImagesAndThumbnails { + images: string[] + thumbnails: string[] +} + +export async function updateViewerStoreImageAndThumbnail< + T extends AStoreDataWithImagesAndThumbnails +>(store: AStore, images: string[]) { + try { + if (typeof images === 'undefined' || !images) { + return null + } + store.data.images = images + const thumbnail_list = [] + for (const base64 of images) { + const thumbnail = await io.createThumbnail(base64, 300) + thumbnail_list.push(thumbnail) + } + + store.data.thumbnails = thumbnail_list + } catch (e) { + console.warn(e) + console.warn('images: ', images) + } +} + +export const resetViewer = () => { + store.updateProperty('images', []) + store.data.thumbnails = [] + store.data.prev_index = -1 + store.data.is_stored = [] + store.data.layers = [] + store.data.class_name = [] + store.data.can_click = true + + mask_store.data.images = [] + mask_store.data.thumbnails = [] + init_store.data.images = [] + init_store.data.thumbnails = [] +} diff --git a/utility/event.js b/utility/event.js deleted file mode 100644 index 85a78f2..0000000 --- a/utility/event.js +++ /dev/null @@ -1,13 +0,0 @@ -const updatePresetMenuEvent = new CustomEvent('updatePresetMenuEvent', { - detail: {}, - bubbles: true, - cancelable: true, - composed: false, -}) -function triggerEvent(query_selector, event) { - document.querySelector(query_selector).dispatchEvent(event) -} -module.exports = { - updatePresetMenuEvent, - triggerEvent, -} diff --git a/utility/general.js b/utility/general.js index c9c32a6..0cbedd2 100644 --- a/utility/general.js +++ b/utility/general.js @@ -51,41 +51,6 @@ function scaleToClosestKeepRatio( function mapRange(x, in_min, in_max, out_min, out_max) { return ((x - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min } -function scaleToRatio( - new_value_1, - old_value_1, - new_value_2, //get ignored - old_value_2, - max_value, - min_value -) { - const ratio = new_value_1 / old_value_1 // 1000/500 = 2 - let final_new_value_2 = old_value_2 * ratio // 500 * 2 = 1000 - let final_new_value_1 = new_value_1 - if (final_new_value_2 > max_value) { - ;[_, final_new_value_1] = scaleToRatio( - max_value, - old_value_2, - new_value_1, //get ignored - old_value_1, - max_value, - min_value - ) - final_new_value_2 = max_value - } else if (final_new_value_2 < min_value) { - ;[_, final_new_value_1] = scaleToRatio( - min_value, - old_value_2, - new_value_1, //get ignored - old_value_1, - max_value, - min_value - ) - final_new_value_2 = min_value - } - - return [final_new_value_1, final_new_value_2] -} function compareVersions(version_1, version_2) { //remove the first character v @@ -137,7 +102,7 @@ function sudoTimer(progress_text = 'Loading ControlNet...') { return timerId } function countNewLines(string) { - const count = (string.match(/\n/g) || []).length + const count = (string.match(/[\n\r]/g) || []).length // console.log(count) return count } @@ -150,7 +115,7 @@ module.exports = { base64UrlToBase64, timer, scaleToClosestKeepRatio, - scaleToRatio, + mapRange, compareVersions, requestOnlineData, diff --git a/utility/html_manip.js b/utility/html_manip.js index 900e418..2cb692f 100644 --- a/utility/html_manip.js +++ b/utility/html_manip.js @@ -1,11 +1,5 @@ ////// Start Prompt////////// -function getPrompt() { - // const prompt = document.getElementById('taPrompt').value - const prompt = multiPrompts.getPrompt().positive - return prompt -} - function autoFillInPrompt(prompt_value) { // document.getElementById('taPrompt').value = prompt_value multiPrompts.setPrompt({ positive: prompt_value }) @@ -15,14 +9,6 @@ function autoFillInPrompt(prompt_value) { ////// Start Negative Prompt////////// -function getNegativePrompt() { - // const negative_prompt = document.getElementById('taNegativePrompt').value - - const negative_prompt = multiPrompts.getPrompt().negative - - return negative_prompt -} - function autoFillInNegativePrompt(negative_prompt_value) { // document.getElementById('taNegativePrompt').value = negative_prompt_value multiPrompts.setPrompt({ negative: negative_prompt_value }) @@ -32,103 +18,8 @@ function autoFillInNegativePrompt(negative_prompt_value) { ////// Start Width////////// -document.getElementById('slWidth').addEventListener('input', (evt) => { - const width = evt.target.value * 64 - - document.getElementById('lWidth').textContent = parseInt(width) - // widthSliderOnChangeEventHandler(evt) - updateResDifferenceLabel() -}) - -document.getElementById('slHeight').addEventListener('input', (evt) => { - const height = evt.target.value * 64 - - document.getElementById('lHeight').textContent = parseInt(height) - // heightSliderOnChangeEventHandler(evt) - updateResDifferenceLabel() -}) - -function widthSliderOnChangeEventHandler(evt) { - let new_width = evt.target.value * 64 - const b_link = getLinkWidthHeightState() - let final_width = new_width - let final_height - if (b_link) { - const current_height = html_manip.getHeight() - ;[final_width, final_height] = general.scaleToRatio( - new_width, - g_old_slider_width, - _, - current_height, - parseInt(evt.target.max * 64), - parseInt(evt.target.min * 64) - ) - - evt.target.value = parseInt(final_width / 64) - html_manip.autoFillInHeight(final_height) - } - - g_old_slider_width = final_width // update the old value, so we can use it later - document.getElementById('lWidth').textContent = parseInt(final_width) -} -document.getElementById('slWidth').addEventListener('change', (evt) => { - widthSliderOnChangeEventHandler(evt) -}) -// document.getElementById('slWidth').addEventListener('change', (evt) => { -// let new_width = evt.target.value * 64 -// const b_link = getLinkWidthHeightState() -// let final_width = new_width -// let final_height -// if (b_link) { -// const current_height = html_manip.getHeight() -// ;[final_width, final_height] = general.scaleToRatio( -// new_width, -// g_old_slider_width, -// _, -// current_height, -// parseInt(evt.target.max * 64), -// parseInt(evt.target.min * 64) -// ) - -// evt.target.value = parseInt(final_width / 64) -// html_manip.autoFillInHeight(final_height) -// } - -// g_old_slider_width = final_width // update the old value, so we can use it later -// document.getElementById('lWidth').textContent = parseInt(final_width) -// }) - -function heightSliderOnChangeEventHandler(evt) { - let new_height = evt.target.value * 64 - - let final_width - let final_height = new_height - const b_link = getLinkWidthHeightState() - if (b_link) { - const current_width = html_manip.getWidth() - ;[final_height, final_width] = general.scaleToRatio( - new_height, - g_old_slider_height, - _, - current_width, - parseInt(evt.target.max * 64), - parseInt(evt.target.min * 64) - ) - - evt.target.value = parseInt(final_height / 64) - html_manip.autoFillInWidth(final_width) - } - g_old_slider_height = final_height // update the old value, so we can use it later - document.getElementById('lHeight').textContent = parseInt(final_height) -} -document.getElementById('slHeight').addEventListener('change', (evt) => { - heightSliderOnChangeEventHandler(evt) -}) - function getWidth() { - slider_width = document.getElementById('slWidth').value - const width = slider_width * 64 - return width + return sd_tab_store.data.width } function getHrWidth() { @@ -142,147 +33,37 @@ function getHrHeight() { const width = slider_width * 64 return width } -function autoFillInWidth(width_value) { - const width_slider = document.getElementById('slHeight') +async function autoFillInWidth(width_value) { + sd_tab_store.data.width = width_value + sd_tab_util.helper_store.data.previous_width = width_value - // g_old_slider_width = width_slider.value * 64 //store the old value - g_old_slider_width = width_value - - document.getElementById('slWidth').value = `${width_value / 64}` - //update the label - document.getElementById('lWidth').innerHTML = `${parseInt(width_value)}` - updateResDifferenceLabel() + sd_tab_store.data.ratio = + await selection.Selection.getImageToSelectionDifference() } ////// End Width////////// ////// Start Height////////// function getHeight() { - slider_value = document.getElementById('slHeight').value - const height = slider_value * 64 - return height + // slider_value = document.getElementById('slHeight').value + // const height = slider_value * 64 + return sd_tab_store.data.height } -function autoFillInHeight(height_value) { - const height_slider = document.getElementById('slHeight') - // g_old_slider_height = height_slider.value * 64 - g_old_slider_height = height_value //store the current value as old value. counterintuitive!. only use old value when the user directly manipulate the slider - - height_slider.value = `${height_value / 64}` +async function autoFillInHeight(height_value) { + sd_tab_util.helper_store.data.previous_height = height_value + sd_tab_store.data.height = height_value //update the label - document.getElementById('lHeight').innerHTML = `${parseInt(height_value)}` - updateResDifferenceLabel() + sd_tab_store.data.ratio = + await selection.Selection.getImageToSelectionDifference() } function autoFillInHRHeight(height_value) { - document.getElementById('hrHeight').value = `${height_value / 64}` - //update the label - document.getElementById('hHeight').innerHTML = `${height_value}` + sd_tab_store.data.hr_resize_y = height_value } -function autoFillInHRWidth(height_value) { - document.getElementById('hrWidth').value = `${height_value / 64}` - //update the label - document.getElementById('hWidth').innerHTML = `${height_value}` -} - -////// End Height////////// - -////// Start Denoising Strength////////// -document - .querySelector('#slDenoisingStrength') - .addEventListener('input', (evt) => { - const label_value = evt.target.value / 100 - // console.log("label_value: ", label_value) - document.getElementById( - 'lDenoisingStrength' - ).innerHTML = `${label_value}` - }) - -//get the value that is relevant to stable diffusion -function getDenoisingStrength() { - const slider_value = document.getElementById('slDenoisingStrength').value - const denoising_strength_value = slider_value / 100.0 - return denoising_strength_value -} - -// display the value the user need to see in all elements related to denoising strength attribute -function autoFillInDenoisingStrength(denoising_strength_value) { - //sd denoising strength value range from [0,1] slider range from [0, 100] - //update the slider - document.getElementById('slDenoisingStrength').value = `${ - denoising_strength_value * 100 - }` - //update the label - document.getElementById( - 'lDenoisingStrength' - ).innerHTML = `${denoising_strength_value}` -} - -////// End Denoising Strength////////// - -////// Start Hi Res Fix////////// - -document.getElementById('chInpaintFullRes').addEventListener('click', (ev) => { - const inpaint_padding_slider = document.getElementById('slInpaintPadding') - - if (ev.target.checked) { - inpaint_padding_slider.style.display = 'block' - } else { - inpaint_padding_slider.style.display = 'none' - } -}) -document.getElementById('chHiResFixs').addEventListener('click', (ev) => { - const container = document.getElementById('hi-res-sliders-container') - - if (ev.target.checked) { - container.style.display = 'flex' - } else { - container.style.display = 'none' - } -}) -//get the value that is relevant to stable diffusion -function getHiResFixs() { - const isChecked = document.getElementById('chHiResFixs').checked - return isChecked -} - -function setHiResFixs(isChecked) { - document.getElementById('chHiResFixs').checked = isChecked -} - -function sliderAddEventListener( - slider_id, - label_id, - multiplier, - fractionDigits = 2 -) { - document.getElementById(slider_id).addEventListener('input', (evt) => { - const sd_value = evt.target.value * multiplier // convert slider value to SD ready value - document.getElementById(label_id).textContent = - Number(sd_value).toFixed(fractionDigits) - }) -} -function sliderAddEventListener_new( - slider_id, - label_id, - slider_start, - slider_end, - sd_start, - sd_end -) { - document.getElementById(slider_id).addEventListener('input', (evt) => { - const sd_value = general.mapRange( - evt.target.value, - slider_start, - slider_end, - sd_start, - sd_end - ) // convert slider value to SD ready value - - document.getElementById(label_id).textContent = - Number(sd_value).toFixed(2) - }) +function autoFillInHRWidth(width_value) { + sd_tab_store.data.hr_resize_x = width_value } //get the stable diffusion ready value from the slider with "slider_id" @@ -383,13 +164,6 @@ function setSliderSdValueByElements( label_element.innerHTML = sd_value.toString() } -//hrWidth is from [1 to 32] * 64 => [64 to 2048] -sliderAddEventListener('hrWidth', 'hWidth', 64) -sliderAddEventListener('hrHeight', 'hHeight', 64) - -//convert hrDenoisingStrength from [1, 100] * 0.01 => [0.01 to 1] -sliderAddEventListener('hrDenoisingStrength', 'hDenoisingStrength', 0.01) - function autoFillInHiResFixs(firstphase_width, firstphase_height) { //update the firstphase width slider and label autoFillInSliderUi(firstphase_width, 'hrWidth', 'hWidth', 1.0 / 64) @@ -442,23 +216,6 @@ function getSamplerElementByName(sampler_name) { } } -function getCheckedSamplerName() { - //we assume that the samplers exist and loaded in html - //return the name of the first checked sampler - try { - return [...document.getElementsByClassName('rbSampler')].filter( - (elm) => elm.checked == true - )[0].value - } catch (e) { - console.warn(e) - } -} -function getMode() { - return [...document.getElementsByClassName('rbMode')].filter( - (e) => e.checked == true - )[0].value -} - function getBackendType() { return [...document.getElementsByClassName('rbBackendType')].filter( (e) => e.checked == true @@ -525,18 +282,6 @@ function selectModelUi(model_hash) { model_element.selected = true } -function autoFillInModel(model_hash) { - try { - // unCheckAllSamplers() - model_element = getModelElementByHash(model_hash) - selectModelUi(model_hash) - // model_element. - const model_title = model_element.dataset.model_title - return model_title - } catch (e) { - console.warn(e) - } -} ////// End Models////////// ////// Start Init Image && Init Image Mask////////// @@ -601,105 +346,8 @@ function setProxyServerStatus(newStatusClass, oldStatusClass) { } ////// End Servers Status ////////// -////// Start Extras ////////// - -sliderAddEventListener('slUpscaleSize', 'lUpscaleSize', 0.1, 1) - -function getUpscaleSize() { - slider_width = document.getElementById('slUpscaleSize').value - const size = slider_width / 10 - return size -} - -sliderAddEventListener('slUpscaler2Visibility', 'lUpscaler2Visibility', 0.1, 1) - -function getUpscaler2Visibility() { - slider_width = document.getElementById('slUpscaler2Visibility').value - const size = slider_width / 10 - return size -} - -sliderAddEventListener('slGFPGANVisibility', 'lGFPGANVisibility', 0.1, 1) - -function getGFPGANVisibility() { - slider_width = document.getElementById('slGFPGANVisibility').value - const size = slider_width / 10 - return size -} - -sliderAddEventListener( - 'slCodeFormerVisibility', - 'lCodeFormerVisibility', - 0.1, - 1 -) - -function getCodeFormerVisibility() { - slider_width = document.getElementById('slCodeFormerVisibility').value - const size = slider_width / 10 - return size -} - -sliderAddEventListener('slCodeFormerWeight', 'lCodeFormerWeight', 0.1, 1) - -function getCodeFormerWeight() { - slider_width = document.getElementById('slCodeFormerWeight').value - const size = slider_width / 10 - return size -} - -////// End Extras ////////// - ////// Start Reset Settings Button ////////// -const defaultSettings = { - model: null, - prompt_shortcut: null, - positive_prompt: '', - negative_prompt: '', - selection_mode: null, - batch_number: 1, - steps: 20, - width: 512, - height: 512, - firstphase_width: 512, - firstphase_height: 512, - cfg: 7, - denoising_strength: 0.7, - hi_res_denoising_strength: 0.7, - mask_blur: 8, - inpaint_at_full_res: false, - hi_res_fix: false, - inpaint_padding: 0, - seed: -1, - samplers: null, - mask_content: null, -} - -const snapshot_btns = Array.from( - document.getElementsByClassName('snapshotButton') -) -snapshot_btns.forEach((element) => - element.addEventListener('click', async () => { - try { - await psapi.snapshot_layerExe() - } catch (e) { - console.warn(e) - } - }) -) - -const reset_btns = Array.from(document.getElementsByClassName('resetButton')) -reset_btns.forEach((element) => - element.addEventListener('click', async () => { - try { - autoFillDefaultSettings(defaultSettings) - } catch (e) { - console.warn(e) - } - }) -) - function getBatchNumber() { // return document.getElementById('tiNumberOfImages').value return document.getElementById('tiNumberOfBatchSize').value @@ -709,67 +357,45 @@ function autoFillInBatchNumber(batch_number) { document.getElementById('tiNumberOfBatchSize').value = String(batch_number) } -function getSteps() { - return document.getElementById('tiNumberOfSteps').value -} -function autoFillInSteps(steps) { - document.getElementById('tiNumberOfSteps').value = String(steps) -} -function autoFillDefaultSettings(default_settings) { - autoFillSettings(default_settings) -} - function setCFG(cfg_value) { - document.getElementById('slCfgScale').value = cfg_value + sd_tab_store.data.cfg = cfg_value } function getCFG() { - return document.getElementById('slCfgScale').value + return sd_tab_store.data.cfg } function autoFillSettings(settings) { try { //reset all UI settings except model selection and sampler selection - autoFillInPrompt(settings['positive_prompt']) - autoFillInNegativePrompt(settings['negative_prompt']) + + multiPrompts.setPrompt({ positive: settings['positive_prompt'] }) + multiPrompts.setPrompt({ negative: settings['negative_prompt'] }) autoFillInBatchNumber(settings['batch_number']) - autoFillInSteps(settings['steps']) + sd_tab_store.data.steps = settings['steps'] autoFillInWidth(settings['width']) autoFillInHeight(settings['height']) autoFillInHiResFixs( settings['firstphase_width'], settings['firstphase_height'] ) - document.getElementById('slCfgScale').value = settings['cfg'] - autoFillInDenoisingStrength(settings['denoising_strength']) + sd_tab_store.data.cfg = settings['cfg'] + sd_tab_store.data.denoising_strength = settings['denoising_strength'] autoFillInSliderUi( settings['hi_res_denoising_strength'], 'hrDenoisingStrength', 'hDenoisingStrength', 100 ) - document.getElementById('slMaskBlur').value = settings['mask_blur'] - document.getElementById('chInpaintFullRes').checked = - settings['inpaint_at_full_res'] - setHiResFixs(settings['hi_res_fix']) - document.getElementById('tiSeed').value = String(settings['seed']) + sd_tab_store.data.mask_blur = settings['mask_blur'] + sd_tab_store.data.inpaint_full_res = settings['inpaint_at_full_res'] + sd_tab_store.data.enable_hr = settings['hi_res_fix'] + sd_tab_store.data.seed = String(settings['seed']) } catch (e) { console.warn(e) } } ////// End Reset Settings Button ////////// -function getMaskBlur() { - const isDisabled = document - .getElementById('slMaskBlur') - .hasAttribute('disabled') - let mask_blur = 0 - if (isDisabled) { - mask_blur = 0 - } else { - mask_blur = document.getElementById('slMaskBlur').value - } - return mask_blur -} function setMaskBlur(mask_blur) { document.getElementById('slMaskBlur').value = mask_blur } @@ -789,12 +415,6 @@ function setPromptShortcut(prompt_shortcut) { document.getElementById('taPromptShortcut').value = JSONInPrettyFormat } -////start selection mode///// -function getSelectionMode() { - return [...document.getElementsByClassName('rbSelectionMode')].filter( - (e) => e.checked == true - )[0].value -} function getMaskContent() { return [...document.getElementsByClassName('rbMaskContent')].filter( (e) => e.checked == true @@ -851,22 +471,6 @@ function addHistoryButtonsHtml(img_html) { return container } -function getSeed() { - const seed = document.getElementById('tiSeed').value - return seed -} -function setSeed(new_seed) { - document.getElementById('tiSeed').value = new_seed -} - -function getMaskExpansion() { - const mask_expansion = document.getElementById('slMaskExpansion').value - return mask_expansion -} - -function setMaskExpansion(mask_expansion) { - document.getElementById('slMaskExpansion').value = mask_expansion -} function updateProgressBarsHtml(new_value, progress_text = 'Progress...') { document.querySelectorAll('.pProgressBars').forEach((bar_elm) => { @@ -888,14 +492,7 @@ function updateProgressBarsHtml(new_value, progress_text = 'Progress...') { // document.querySelector('#pProgressBar').value } ///end selection mode//// -function getLinkWidthHeightState() { - const state_str = document.getElementById('linkWidthHeight').dataset.b_link // sometime it's true and other time it's "true" - const b_state = state_str.toString() === 'true' ? true : false - return b_state -} -function setLinkWidthHeightState(state) { - document.getElementById('linkWidthHeight').dataset.b_link = state -} + function isSquareThumbnail() { return document.getElementById('chSquareThumbnail').checked } @@ -1071,12 +668,10 @@ function getUseSilentMode() { } module.exports = { - getPrompt, autoFillInPrompt, - getNegativePrompt, + autoFillInNegativePrompt, - getDenoisingStrength, - autoFillInDenoisingStrength, + getWidth, autoFillInWidth, getHeight, @@ -1084,22 +679,19 @@ module.exports = { getSliderSdValue, setSliderSdValue, autoFillInHiResFixs, - getHiResFixs, - setHiResFixs, + autoFillInSliderUi, - getCheckedSamplerName, + autoFillInSampler, - autoFillInModel, - getMode, + setInitImageSrc, setInitImageMaskSrc, setAutomaticStatus, setProxyServerStatus, - defaultSettings, - autoFillDefaultSettings, + autoFillSettings, - getMaskBlur, + setMaskBlur, autoFillInHRHeight, @@ -1107,10 +699,9 @@ module.exports = { getPromptShortcut, setPromptShortcut, getModelHashByTitle, - getSelectionMode, + autoFillInInpaintMaskWeight, - autoFillInSteps, - getSteps, + getBatchNumber, autoFillInBatchNumber, getHrWidth, @@ -1121,21 +712,11 @@ module.exports = { setMaskContent, addHistoryButtonsHtml, - getSeed, - setSeed, - getMaskExpansion, - setMaskExpansion, - getUpscaleSize, - getUpscaler2Visibility, - getCodeFormerVisibility, - getGFPGANVisibility, - getCodeFormerWeight, updateProgressBarsHtml, getBackendType, getHordeApiKey, setProgressImageSrc, - getLinkWidthHeightState, - setLinkWidthHeightState, + isSquareThumbnail, setControlImageSrc, @@ -1150,7 +731,7 @@ module.exports = { getSliderSdValue_Old, getSelectedRadioButtonElement, getInitImageMaskElement, - sliderAddEventListener_new, + getSliderSdValueByElement, setSliderSdValueByElements, populateMenuByElement, diff --git a/utility/notification.js b/utility/notification.js index a521071..f2764e3 100644 --- a/utility/notification.js +++ b/utility/notification.js @@ -6,7 +6,7 @@ class Notification { static async webuiIsOffline() { const r1 = await dialog_box.prompt( 'Automatic1111 is Offline', - "make sure Automatic1111 is running in the background, or select the 'native horde' option from the horde tab", + 'make sure Automatic1111 is running in the background', ['Cancel', 'OK'] ) @@ -93,7 +93,7 @@ class Notification { psapi.selectMarqueeRectangularToolExe() return false // should this be false?! what does true and false means in this context?! Yes: it should be false since boolean value represent wither we have an active selection area or not } else if (r1 === button_label) { - await activateSessionSelectionArea() + await selection_ts.activateSessionSelectionArea() return true } return false diff --git a/utility/presets/preset.js b/utility/presets/preset.js deleted file mode 100644 index 81096c8..0000000 --- a/utility/presets/preset.js +++ /dev/null @@ -1,406 +0,0 @@ -const io = require('../io') -const html_manip = require('../html_manip') -const Enum = require('../../enum') -const event = require('../event') - -let settings = { - model: null, - prompt_shortcut: null, - positive_prompt: null, - negative_prompt: null, - selection_mode: null, - batch_number: null, - steps: null, - width: null, - height: null, - firstphase_width: null, - firstphase_height: null, - cfg: null, - denoising_strength: null, - hi_res_denoising_strength: null, - mask_blur: null, - inpaint_at_full_res: null, - hi_res_fix: null, - inpaint_padding: null, - seed: null, - samplers: null, - mask_content: null, -} - -let LatentNoiseSettings = { - model: null, - prompt_shortcut: null, - positive_prompt: null, - negative_prompt: null, - generation_mode: null, - batch_number: null, - steps: null, - width: null, - height: null, - firstphase_width: null, - firstphase_height: null, - cfg: null, - denoising_strength: 0.92, - hi_res_denoising_strength: null, - mask_blur: null, - inpaint_at_full_res: null, - hi_res_fix: null, - inpaint_padding: null, - seed: null, - samplers: null, - mask_content: '2', -} - -let FillSettings = { - model: null, - prompt_shortcut: null, - positive_prompt: null, - negative_prompt: null, - generation_mode: null, - batch_number: null, - steps: null, - width: null, - height: null, - firstphase_width: null, - firstphase_height: null, - cfg: null, - denoising_strength: 0.7, - hi_res_denoising_strength: null, - mask_blur: null, - inpaint_at_full_res: null, - hi_res_fix: null, - inpaint_padding: null, - seed: null, - samplers: null, - mask_content: '0', -} -let OriginalSettings = { - model: null, - prompt_shortcut: null, - positive_prompt: null, - negative_prompt: null, - generation_mode: null, - batch_number: null, - steps: null, - width: null, - height: null, - firstphase_width: null, - firstphase_height: null, - cfg: null, - denoising_strength: 0.7, - hi_res_denoising_strength: null, - mask_blur: null, - inpaint_at_full_res: null, - hi_res_fix: null, - inpaint_padding: null, - seed: null, - samplers: null, - mask_content: '1', -} -let HealBrushSettings = { - model: null, - prompt_shortcut: null, - positive_prompt: null, - negative_prompt: null, - generation_mode: null, - batch_number: null, - steps: '25', - width: null, - height: null, - firstphase_width: null, - firstphase_height: null, - cfg: '9', - denoising_strength: 0.92, - hi_res_denoising_strength: null, - mask_blur: 1, - inpaint_at_full_res: null, - hi_res_fix: null, - inpaint_padding: null, - seed: null, - samplers: null, - mask_content: '2', - mask_expansion: 2, -} - -function nullAllSettings() {} - -class Preset { - constructor() {} - - loadPresetFromJson(preset_path) {} - savePresetToJson(preset_path, settings) {} -} - -function getPresetSettingsHtml() { - const value_str = document.getElementById('taPresetSettings').value - const value_json = JSON.parse(value_str) - return value_json -} -function setPresetSettingsHtml(preset_settings) { - const JSONInPrettyFormat = JSON.stringify(preset_settings, undefined, 7) - preset_settings_element = document.getElementById('taPresetSettings') - preset_settings_element.value = JSONInPrettyFormat - - const new_lines_count = general.countNewLines(JSONInPrettyFormat) - new_lines_count - preset_settings_element.style.height = - Math.min(new_lines_count * 12 + 100, 800).toString() + 'px' -} - -function getPresetName() { - const preset_name = document.getElementById('tiPresetName').value - return preset_name -} -function setPresetName(preset_name) { - document.getElementById('tiPresetName').value = preset_name -} - -function getPresetSettings(preset_type) { - let preset_settings - if (preset_type === Enum.PresetTypeEnum['SDPreset']) { - preset_settings = g_ui_settings_object.getSettings() - } else if (preset_type === Enum.PresetTypeEnum['ControlNetPreset']) { - const { getUnitsData } = - require('../../typescripts/dist/bundle').control_net // only import ControlNetUnit to avoid circular dependency - preset_settings = getUnitsData() - } - return preset_settings -} - -function getPresetType() { - const presetType = document.getElementById('rgPresetType').selected - - return presetType -} - -document.getElementById('btnNewPreset').addEventListener('click', () => { - // const g_ui_settings_object = getUISettingsObject() - - const preset_type = getPresetType() - const preset_settings = getPresetSettings(preset_type) - - // const settings = g_ui_settings_object.getSettings() - - setPresetSettingsHtml(preset_settings) - - const preset_name = getPresetName() - setPresetNameLabel(preset_name) -}) - -function getPresetNameLabel() { - //use presetNameLabel as the final name for a preset - const preset_name = document.getElementById('lPresetName').textContent - return preset_name -} -function setPresetNameLabel(preset_name) { - document.getElementById('lPresetName').textContent = preset_name.trim() -} - -async function populatePresetMenu() { - // presets = ['preset_1', 'preset_2', 'preset_3'] - const preset_type = getPresetType() - const presets = await getAllCustomPresetsSettings(preset_type) - const presets_names = Object.keys(presets) - html_manip.populateMenu( - 'mSettingTabPresetMenu', - 'mPresetMenuItemClass', - presets_names, - (item, item_html_element) => { - item_html_element.innerHTML = item - } - ) -} -async function deletePreset() { - try { - const preset_name = html_manip.getSelectedMenuItemTextContent( - 'mSettingTabPresetMenu' - ) - const preset_file_name = preset_name + '.json' - - const preset_type = getPresetType() - const preset_folder_name = mapPresetTypeToPresetFolder(preset_type) - const custom_preset_entry = await io.IOFolder.getCustomPresetFolder( - preset_folder_name - ) - - await io.IOJson.deleteFile(custom_preset_entry, preset_file_name) - html_manip.unselectMenuItem('mSettingTabPresetMenu') // unselect the custom preset menu - setPresetSettingsHtml({}) //reset preset settings text area - setPresetName('') - setPresetNameLabel('') - await populatePresetMenu() // update the custom preset Menu - triggerUpdatePresetMenu(preset_type) - } catch (e) { - console.warn(e) - } -} - -async function getCustomPresetEntries(preset_folder_name) { - const custom_preset_entry = await io.IOFolder.getCustomPresetFolder( - preset_folder_name - ) - - const custom_preset_entries = await io.IOJson.getJsonEntries( - custom_preset_entry - ) - - return custom_preset_entries -} - -async function loadPresetSettingsFromFile(preset_file_name, preset_type) { - // const preset_type = getPresetType() - - const preset_folder_name = mapPresetTypeToPresetFolder(preset_type) - const custom_preset_entry = await io.IOFolder.getCustomPresetFolder( - preset_folder_name - ) - let preset_settings = {} - try { - preset_settings = await io.IOJson.loadJsonFromFile( - custom_preset_entry, - preset_file_name - ) - } catch (e) { - console.warn(e) - } - return preset_settings -} -async function getAllCustomPresetsSettings(preset_type) { - const preset_folder_name = mapPresetTypeToPresetFolder(preset_type) - const custom_preset_entries = await getCustomPresetEntries( - preset_folder_name - ) - let custom_presets = {} - for (const entry of custom_preset_entries) { - const preset_name = entry.name.split('.json')[0] - let preset_settings = await loadPresetSettingsFromFile( - entry.name, - preset_type - ) - - custom_presets[preset_name] = preset_settings - } - return custom_presets -} - -function mapPresetTypeToPresetFolder(preset_type) { - let preset_folder - - if (preset_type === Enum.PresetTypeEnum['SDPreset']) { - preset_folder = 'custom_preset' - } else if (preset_type === Enum.PresetTypeEnum['ControlNetPreset']) { - preset_folder = 'controlnet_preset' - } - return preset_folder -} - -function triggerUpdatePresetMenu(preset_type) { - let menu_id - if (preset_type === Enum.PresetTypeEnum['SDPreset']) { - menu_id = '#mPresetMenu' - } else if (preset_type === Enum.PresetTypeEnum['ControlNetPreset']) { - menu_id = '#mControlNetPresetMenu' - } - event.triggerEvent(menu_id, event.updatePresetMenuEvent) -} -Array.from(document.getElementsByClassName('rbPresetType')).forEach((rb) => { - rb.addEventListener('click', async () => { - const preset_type = rb.value - await populatePresetMenu() - }) -}) - -document.getElementById('btnSavePreset').addEventListener('click', async () => { - //save preset settings from textarea to json file - //reload the preset menu - const preset_type = getPresetType() - const custom_preset_folder_name = mapPresetTypeToPresetFolder(preset_type) - const custom_preset_entry = await io.IOFolder.getCustomPresetFolder( - custom_preset_folder_name - ) - const preset_settings = getPresetSettingsHtml() - const preset_name = getPresetNameLabel() - - //check if the file exist and prompt the user to override it or cancel - await io.IOJson.saveJsonToFileExe( - preset_settings, - custom_preset_entry, - preset_name + '.json' - ) - await populatePresetMenu() - triggerUpdatePresetMenu(preset_type) - html_manip.selectMenuItem('mSettingTabPresetMenu', preset_name) -}) -document - .getElementById('btnDeletePreset') - .addEventListener('click', async () => { - await deletePreset() - }) - -document.getElementById('tiPresetName').addEventListener('input', () => { - //save preset settings from textarea to json file - //reload the preset menu - const preset_name = getPresetName() - setPresetNameLabel(preset_name) - //check if the file exist and prompt the user to override it or cancel -}) -document - .getElementById('mSettingTabPresetMenu') - .addEventListener('input', () => { - //Note: is this correct?! why use Input and change events together - //save preset settings from textarea to json file - //reload the preset menu - const preset_name = getPresetName() - setPresetNameLabel(preset_name) - //check if the file exist and prompt the user to override it or cancel - }) - -document - .getElementById('mSettingTabPresetMenu') - .addEventListener('change', async (evt) => { - try { - const preset_index = evt.target.selectedIndex - const preset_name = evt.target.options[preset_index].textContent - const preset_type = getPresetType() - setPresetName(preset_name) - setPresetNameLabel(preset_name) - - const preset_settings = await loadPresetSettingsFromFile( - preset_name + '.json', - preset_type - ) - setPresetSettingsHtml(preset_settings) - } catch (e) {} - }) - -document - .getElementById('mPresetMenu') - .addEventListener('updatePresetMenuEvent', async (event) => { - // console.log("I'm listening on a custom event") - const { populatePresetMenu } = require('../ui') - await populatePresetMenu() - }) - -async function initializePresetTab() { - try { - await populatePresetMenu() - - const selected_rb = - html_manip.getSelectedRadioButtonElement('rbPresetType') - selected_rb.click() // to trigger the click event which will update the setting preset menu according to the preset type - } catch (e) { - console.error(e) - } -} -initializePresetTab() -module.exports = { - LatentNoiseSettings, - FillSettings, - OriginalSettings, - HealBrushSettings, - populatePresetMenu, - getCustomPresetEntries, - loadPresetSettingsFromFile, - getAllCustomPresetsSettings, - initializePresetTab, -} diff --git a/utility/sdapi/python_replacement.js b/utility/sdapi/python_replacement.js index 89d30ad..2c738f8 100644 --- a/utility/sdapi/python_replacement.js +++ b/utility/sdapi/python_replacement.js @@ -222,7 +222,7 @@ async function txt2ImgRequest(payload) { // const request_path = '/sdapi/v1/txt2img' } function getExtensionUrl() { - const extension_type = settings_tab.getExtensionType() + const extension_type = settings_tab_ts.store.data.extension_type let extension_url if (extension_type === 'auto1111_extension') { @@ -305,31 +305,6 @@ async function img2ImgRequest(sd_url, payload) { payload['prompt'] = new_prompt payload['negative_prompt'] = new_negative_prompt } - // init_img_dir = "./init_images" - // init_img_name = payload['init_image_name'] - // init_img = Image.open(f"{init_img_dir}/{init_img_name}") - // init_img_str = img_2_b64(init_img) - // payload['init_images'] = [init_img_str] - - // init_img_mask_name = payload.get('init_image_mask_name',"") - - // #only if image exist then try to open it - - // if(len(init_img_mask_name) > 0): - // init_img_mask = Image.open(f"{init_img_dir}/{init_img_mask_name}") - - // if (payload['use_sharp_mask'] === false && payload['mask']) { - // //only if mask is available and sharp_mask is off - // // use blurry and expanded mask - // const iterations = payload['mask_expansion'] - // const mask = await maskExpansionRequest(payload['mask'], iterations) - // if (mask) { - // payload['mask'] = mask - // } - // } - - // print(type(init_img_str)) - // #request the images to be generated const endpoint = 'sdapi/v1/img2img' diff --git a/utility/session.js b/utility/session.js index 5d4a89f..25dfd51 100644 --- a/utility/session.js +++ b/utility/session.js @@ -6,6 +6,7 @@ const Enum = require('../enum') const { base64ToBase64Url } = require('./general') const html_manip = require('./html_manip') const layer_util = require('./layer') + const SessionState = { Active: 'active', Inactive: 'inactive', @@ -181,21 +182,16 @@ async function getSettings(session_data) { let payload = {} try { - const extension_type = settings_tab.getExtensionType() // get the extension type + const extension_type = settings_tab_ts.store.data.extension_type // get the extension type payload['selection_info'] = session_data.selectionInfo - const numberOfBatchSize = parseInt( - document.querySelector('#tiNumberOfBatchSize').value - ) - const numberOfSteps = document.querySelector('#tiNumberOfSteps').value - const prompt = html_manip.getPrompt() - const negative_prompt = html_manip.getNegativePrompt() - const hi_res_fix = html_manip.getHiResFixs() - // console.log("prompt:",prompt) - // console.log("negative_prompt:",negative_prompt) - const model_index = document.querySelector('#mModelsMenu').selectedIndex - const upscaler = document.querySelector('#hrModelsMenu').value - const cfg_scale = document.querySelector('#slCfgScale').value - // const model_index = document.querySelector("#") + const numberOfBatchSize = parseInt(sd_tab_store.data.batch_size) + + const prompt = multiPrompts.getPrompt().positive + const negative_prompt = multiPrompts.getPrompt().negative + const hi_res_fix = sd_tab_store.data.enable_hr + + const upscaler = sd_tab_store.data.hr_upscaler + const cfg_scale = sd_tab_store.data.cfg function calculateSeed(init_seed, batch_index, batch_size) { if (init_seed === -1) return -1 @@ -203,25 +199,25 @@ async function getSettings(session_data) { return seed } - const init_seed = parseInt(document.querySelector('#tiSeed').value) + const init_seed = parseInt(sd_tab_store.data.seed) const seed = calculateSeed( init_seed, g_current_batch_index, numberOfBatchSize ) - // const mask_blur = document.querySelector('#slMaskBlur').value - const use_sharp_mask = settings_tab.getUseSharpMask() - const mask_blur = html_manip.getMaskBlur() - const mask_expansion = document.getElementById('slMaskExpansion').value + const use_sharp_mask = settings_tab_ts.store.data.extension_type + const mask_blur = settings_tab_ts.store.data.use_sharp_mask + ? 0 + : sd_tab_store.data.mask_blur + const mask_expansion = sd_tab_store.data.mask_expansion const inpaint_full_res_padding = - document.querySelector('#slInpaintPadding').value + sd_tab_store.data.inpaint_full_res_padding // console.dir(numberOfImages) - const bUsePromptShortcut = document.getElementById( - 'chUsePromptShortcut' - ).checked + const bUsePromptShortcut = + settings_tab_ts.store.data.use_prompt_shortcut let prompt_shortcut_ui_dict = {} try { let prompt_shortcut_string = @@ -236,46 +232,33 @@ async function getSettings(session_data) { // const slider_width = document.getElementById("slWidth").value // gWidth = getWidthFromSlider(slider_width) - const original_width = html_manip.getWidth() - const original_height = html_manip.getHeight() + const original_width = sd_tab_store.data.width + const original_height = sd_tab_store.data.height const width = general.nearestMultiple(original_width, 64) const height = general.nearestMultiple(original_height, 64) - const hWidth = html_manip.getSliderSdValue_Old('hrWidth', 64) - const hHeight = html_manip.getSliderSdValue_Old('hrHeight', 64) - const hSteps = html_manip.getSliderSdValue_Old('hrNumberOfSteps', 1) //const hScale = html_manip.getSliderSdValue_Old('hrScale',1) - console.log('Check') const uniqueDocumentId = await getUniqueDocumentId() - const h_denoising_strength = html_manip.getSliderSdValue_Old( - 'hrDenoisingStrength', - 0.01 - ) - console.log('Check2') + const h_denoising_strength = sd_tab_store.data.hr_denoising_strength //Note: store the sampler names in json file if auto is offline or auto api is unmounted - const sampler_name = html_manip.getCheckedSamplerName() + const sampler_name = sd_tab_store.data.sampler_name - const mode = html_manip.getMode() - const b_restore_faces = - document.getElementById('chRestoreFaces').checked + const mode = sd_tab_store.data.rb_mode + const b_restore_faces = sd_tab_store.data.restore_faces let denoising_strength = h_denoising_strength if (mode == 'inpaint' || mode == 'outpaint') { - var g_use_mask_image = true - payload['inpaint_full_res'] = - document.getElementById('chInpaintFullRes').checked - payload['inpaint_full_res_padding'] = inpaint_full_res_padding * 4 + payload['inpaint_full_res'] = sd_tab_store.data.inpaint_full_res - console.log('g_use_mask_image is ', g_use_mask_image) - console.log('g_init_image_mask_name is ', g_init_image_mask_name) - payload['init_image_mask_name'] = g_init_image_mask_name - payload['inpainting_fill'] = html_manip.getMaskContent() + payload['inpaint_full_res_padding'] = inpaint_full_res_padding + + payload['inpainting_fill'] = sd_tab_store.data.inpainting_fill payload['mask_expansion'] = mask_expansion - // payload['mask'] = g_generation_session.activeBase64MaskImage + payload['mask'] = session_data?.mask payload['expanded_mask'] = session_data?.mask if ( @@ -294,16 +277,10 @@ async function getSettings(session_data) { if (expanded_mask) { payload['expanded_mask'] = expanded_mask payload['mask'] = expanded_mask - session_ts.store.data.expanded_mask = expanded_mask + session_store.data.expanded_mask = expanded_mask } } // viewer.store.mask = payload['mask'] // make sure - } else if (mode == 'img2img') { - var g_use_mask_image = false - delete payload['inpaint_full_res'] // inpaint full res is not available in img2img mode - delete payload['inpaint_full_res_padding'] - delete payload['init_image_mask_name'] - delete payload['inpainting_fill'] } if ( @@ -311,19 +288,14 @@ async function getSettings(session_data) { g_sd_mode == 'inpaint' || g_sd_mode == 'outpaint' ) { - // const { init_image, mask } = io.getOutpaintInitImageAndMask() - console.log(`g_use_mask_image:? ${g_use_mask_image}`) - - denoising_strength = html_manip.getDenoisingStrength() + denoising_strength = sd_tab_store.data.denoising_strength payload['denoising_strength'] = denoising_strength - payload['init_image_name'] = g_init_image_name payload['init_images'] = [session_data?.init_image] - // payload['init_images'] = [ - // g_generation_session.activeBase64InitImage, - // // init_image, - // ] - payload['image_cfg_scale'] = sd_tab.getImageCfgScaleSDValue() // we may need to check if model is pix2pix + + if (settings_tab_ts.store.data.use_image_cfg_scale_slider) { + payload['image_cfg_scale'] = sd_tab_store.data.image_cfg_scale // we may need to check if model is pix2pix + } if ( scripts.script_store.isInstalled() && @@ -336,13 +308,8 @@ async function getSettings(session_data) { payload['script_name'] = scripts.script_store.selected_script_name //'Ultimate SD upscale' } - } else { - delete payload['script_args'] - delete payload['script_name'] } - // payload['script_args'] = [] - function setAlwaysOnScripts() { const data = after_detailer_script.store.toJsFunc().data // console.log('setAlwaysOnScripts=> data:', data) @@ -405,37 +372,13 @@ async function getSettings(session_data) { } if (hi_res_fix && width >= 512 && height >= 512) { - const hr_scale = sd_tab.getHrScaleSliderSDValue() - payload['enable_hr'] = hi_res_fix - // payload['firstphase_width'] = width - // payload['firstphase_height'] = height - // payload['hr_resize_x'] = hWidth - // payload['hr_resize_y'] = hHeight - payload['hr_scale'] = hr_scale // Scale + payload['hr_scale'] = sd_tab_store.data.hr_scale // Scale payload['hr_upscaler'] = upscaler // Upscaler - payload['hr_second_pass_steps'] = hSteps // Number of Steps - } else { - //fix hi res bug: if we include firstphase_width or firstphase_height in the payload, - // sd api will use them instead of using width and height variables, even when enable_hr is set to "false" - delete payload['enable_hr'] - // delete payload['firstphase_width'] - // delete payload['firstphase_height'] + payload['hr_second_pass_steps'] = + sd_tab_store.data.hr_second_pass_steps } - //work with the hord - - // const script_args_json = { - // model: "Anything Diffusion", - // nsfw: false, - // shared_laion: false, - // seed_variation: 1, - // post_processing_1: "None", - // post_processing_2: "None", - // post_processing_3: "None" - // } - // const script_args = Object.values(script_args_json) - const backend_type = html_manip.getBackendType() if (backend_type === backendTypeEnum['Auto1111HordeExtension']) { payload['script_name'] = script_horde.script_name @@ -477,7 +420,7 @@ async function getSettings(session_data) { ...payload, // prompt: prompt, // negative_prompt: negative_prompt, - steps: numberOfSteps, + steps: sd_tab_store.data.steps, // n_iter: numberOfImages, sampler_index: sampler_name, width: width, diff --git a/utility/tab/sd.js b/utility/tab/sd.js deleted file mode 100644 index e9ab674..0000000 --- a/utility/tab/sd.js +++ /dev/null @@ -1,411 +0,0 @@ -const general = require('../general') -const thumbnail = require('../../thumbnail') -const html_manip = require('../html_manip') -const api = require('../api') -const psapi = require('../../psapi') -const sdapi = require('../../sdapi_py_re') -const Enum = require('../../enum') -//REFACTOR: move to notification.js - -async function requestGetHiResUpscalers() { - try { - const full_url = `${g_sd_url}/sdapi/v1/upscalers` - let upscalers = await api.requestGet(full_url) - return [ - 'Latent', - 'Latent (antialiased)', - 'Latent (bicubic)', - 'Latent (bicubic antialiased)', - 'Latent (nearest)', - 'Latent (nearest-exact)', - ...upscalers.map((upscaler) => upscaler.name), - ] - } catch (e) { - console.warn('requestGetHiResUpscalers:', e) - return [ - 'Latent', - 'Latent (antialiased)', - 'Latent (bicubic)', - 'Latent (bicubic antialiased)', - 'Latent (nearest)', - 'Latent (nearest-exact)', - ] - } -} -async function promptForUpdate(header_message, long_message) { - const shell = require('uxp').shell - - ;(async () => { - const buttons = ['Cancel', 'OK'] - const r1 = await dialog_box.prompt( - header_message, - long_message, - buttons - // 'Please Update you Plugin. it will take about 10 seconds to update', - // 'update from discord, update from github'[ - // ['Cancel', 'Discord', 'Github'] - // ('Cancel', 'OK') - // ] - ) - try { - let url - if (r1 === 'Cancel') { - /* cancelled or No */ - console.log('cancel') - } else if (r1 === 'Github') { - url = - 'https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin' - // await py_re.openUrlRequest(url) - } else if (r1 === 'Discord') { - console.log('Discord') - // url = 'https://discord.gg/3mVEtrddXJ' - // url = 'https://discord.gg/YkUJXYWK3c' - // await py_re.openUrlRequest(url) - } else if (r1 === 'Ok') { - } - // console.log('url: ', url) - } catch (e) { - console.warn(e, url) - } - })() -} - -async function updateClickEventHandler(current_version) { - try { - const online_data = await general.requestOnlineData() - const b_need_update = general.compareVersions( - current_version, - online_data.new_version - ) - - let header_message = "You're Plugin is up to date." - let long_message = '' - if (b_need_update) { - header_message = `New Version is Available (${online_data.new_version})` - long_message = online_data.update_message - } - - await promptForUpdate(header_message, long_message) - } catch (e) { - console.warn(e) - } -} - -function viewMaskExpansion() { - if (session_ts.store.data.expanded_mask) { - const mask_src = general.base64ToBase64Url( - session_ts.store.data.expanded_mask - ) - html_manip.setInitImageMaskSrc(mask_src) - } else { - console.log( - 'the mask has not been expanded, g_generation_session.base64maskExpansionImage is empty' - ) - } -} -function viewDrawnMask() { - //this is the generated mask or user drawn mask, but it's not the mask after expansion - if (session_ts.store.data.mask) { - const mask_src = general.base64ToBase64Url(session_ts.store.data.mask) - html_manip.setInitImageMaskSrc(mask_src) - } else { - console.log('no mask is available') - } -} - -async function clipInterrogate() { - try { - const width = html_manip.getWidth() - const height = html_manip.getHeight() - const selectionInfo = await psapi.getSelectionInfoExe() - - const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New( - width, - height, - selectionInfo, - true - ) - - const url = `${g_sd_url}/sdapi/v1/interrogate` - - const payload = { - image: base64, - model: 'clip', - } - const result_json = await api.requestPost(url, payload) - console.log(result_json) - return result_json - } catch (e) { - console.warn(e) - } -} - -function getHrScaleSliderSDValue() { - sd_value = html_manip.getSliderSdValue('hrScaleSlider', 1, 100, 1, 4) - return sd_value -} -function setHrScaleSliderSDValue(sd_value) { - const slider_id = 'hrScaleSlider' - const label_id = 'hrScaleLabel' - html_manip.setSliderSdValue(slider_id, label_id, sd_value, 1, 100, 1, 4) -} -function getImageCfgScaleSDValue() { - sd_value = html_manip.getSliderSdValue('slImageCfgScale', 0, 30, 0, 3) - return sd_value -} -function setImageCfgScaleSDValue(sd_value) { - const slider_id = 'slImageCfgScale' - const label_id = 'lImageCfgScale' - - html_manip.setSliderSdValue(slider_id, label_id, sd_value, 0, 30, 0, 3) -} - -function updateHrScaleFromToLabel() { - //get width and height - //get hr scale by - //find the hr scale and height - - const hr_scale = getHrScaleSliderSDValue() - const [width, height] = [html_manip.getWidth(), html_manip.getHeight()] - const [hr_width, hr_height] = [ - parseInt(width * hr_scale), - parseInt(height * hr_scale), - ] - document.getElementById( - 'lHrScaleFromTo' - ).textContent = `${width}x${height} -> ${hr_width}x${hr_height}` -} -function getLoraModelPrompt(lora_model_name) { - return `` -} -async function populateLoraModelMenu() { - try { - const lora_models = await sdapi.requestLoraModels() - const lora_models_names = lora_models.map( - (model_data) => model_data.name - ) - - document.getElementById('mLoraModelMenu').innerHTML = '' - - html_manip.populateMenu( - 'mLoraModelMenu', - 'mLoraModelItemClass', - lora_models_names, - (item, item_html_element) => { - item_html_element.innerHTML = item - item_html_element.onclick = () => { - const lora_prompt = getLoraModelPrompt(item) - const prompt = html_manip.getPrompt() - html_manip.autoFillInPrompt(`${prompt} ${lora_prompt}`) - } - }, - false, - 'Select Lora' - ) - } catch (e) { - console.warn('populateLoraModelMenu error: ', e) - } -} - -function displayImageCfgScaleSlider(mode) { - const b_slider_enabled = document.getElementById( - 'chUseImageCfgScaleSlider' - ).checked - if (b_slider_enabled) { - if (mode === Enum.generationModeEnum['Txt2Img']) { - document.getElementById('slImageCfgScale').style.display = 'none' - } else if (mode === Enum.generationModeEnum['Img2Img']) { - document.getElementById('slImageCfgScale').style.display = 'block' - } else if (mode === Enum.generationModeEnum['Inpaint']) { - document.getElementById('slImageCfgScale').style.display = 'block' - } else if (mode === Enum.generationModeEnum['Outpaint']) { - document.getElementById('slImageCfgScale').style.display = 'none' - } else { - document.getElementById('slImageCfgScale').style.display = 'none' - } - } else { - document.getElementById('slImageCfgScale').style.display = 'none' - } -} -function initInitMaskElement() { - //make init mask image use the thumbnail class with buttons - const mask_image_html = html_manip.getInitImageMaskElement() - const mask_parent_element = mask_image_html.parentElement - - this.thumbnail_container = thumbnail.Thumbnail.wrapImgInContainer( - mask_image_html, - 'viewer-image-container' - ) - mask_parent_element.appendChild(thumbnail_container) - thumbnail.Thumbnail.addSPButtonToContainer( - this.thumbnail_container, - 'svg_sp_btn', - 'view original mask', - - viewDrawnMask, - null - ) - thumbnail.Thumbnail.addSPButtonToContainer( - this.thumbnail_container, - 'svg_sp_btn_expand', - 'view modified mask', - - viewMaskExpansion, - null - ) - populateLoraModelMenu() // no need for await -} - -async function refreshSDTab() { - populateLoraModelMenu() -} -document.getElementById('hrScaleSlider').addEventListener('input', (evt) => { - const sd_value = getHrScaleSliderSDValue() - setHrScaleSliderSDValue(sd_value.toFixed(2)) - updateHrScaleFromToLabel() -}) -document.getElementById('btnUpdate').addEventListener('click', async () => { - await updateClickEventHandler(g_version) -}) - -document - .getElementById('slMaskExpansion') - .addEventListener('change', async (evt) => { - const mask = session_ts.store.data.preprocessed_mask - const iterations = parseInt(evt.target.value) - - const mask_blur = html_manip.getMaskBlur() - session_ts.store.data.expanded_mask = await session_ts.getExpandedMask( - mask, - iterations, - mask_blur - ) - if (session_ts.store.data.expanded_mask) { - viewMaskExpansion() - } - }) - -document - .getElementById('slMaskBlur') - .addEventListener('change', async (evt) => { - const mask = session_ts.store.data.preprocessed_mask - const iterations = parseInt( - document.getElementById('slMaskExpansion').value - ) - const mask_blur = parseInt(evt.target.value) - session_ts.store.data.expanded_mask = await session_ts.getExpandedMask( - mask, - iterations, - mask_blur - ) - if (session_ts.store.data.expanded_mask) { - viewMaskExpansion() - } - }) -document - .getElementById('btnInterrogate') - .addEventListener('click', async () => { - // start sudo timer after 1 seconds delay - setTimeout(() => { - g_generation_session.sudo_timer_id = - general.sudoTimer('Interrogate') - }, 1000) - const interrogate_result = await clipInterrogate() - - if (interrogate_result.caption) { - html_manip.autoFillInPrompt(interrogate_result.caption) - } - - // after the clipInterrogate finish stop the timer - - html_manip.updateProgressBarsHtml(0, 'No work in progress') - g_generation_session.sudo_timer_id = clearInterval( - g_generation_session.sudo_timer_id - ) - }) - -function ctrlBackspaceDelete(text) { - try { - let index = text.indexOf(String.fromCharCode(127)) - let new_text = text - if (index >= 0) { - // Ctrl + Enter pressed - console.log('Ctrl + Enter pressed') - - function ctrlBackspaceDeleteLogic(string, index) { - // if (index < 1) { - // return string - // } - // let i = index - 1 - // while ( - // i > 0 && - // /\s/.test(string[i - 1]) === /\s/.test(string[i]) - // ) { - // i-- - // } - // return string.slice(0, i) + string.slice(index) - - if (index < 1) { - return string - } - let i = index - 1 - if (/\s/.test(string[i])) { - while (i > 0 && /\s/.test(string[i - 1])) { - i-- - } - } else { - while ( - i > 0 && - /\s/.test(string[i - 1]) === /\s/.test(string[i]) - ) { - i-- - } - } - return string.slice(0, i) + string.slice(index) - } - new_text = ctrlBackspaceDeleteLogic(text, index + 1) //+ 1 to also delete the backspace delete char - } - - return new_text - } catch (error) { - console.warn(error) - } -} - -// document.getElementById('taPrompt').addEventListener('input', (event) => { -// -// const value = event.target.value -// console.log('value: ', value) -// let index = value.indexOf(String.fromCharCode(127)) -// console.log('index:', index) -// const new_text = ctrlBackspaceDelete(value) -// event.target.value = new_text -// console.log('new_text: ', new_text) -// }) -function initSDTab() { - initInitMaskElement() - html_manip.sliderAddEventListener_new( - 'slImageCfgScale', - 'lImageCfgScale', - 0, - 30, - 0, - 3 - ) -} - -initSDTab() -module.exports = { - updateClickEventHandler, - viewMaskExpansion, - viewDrawnMask, - clipInterrogate, - getHrScaleSliderSDValue, - getLoraModelPrompt, - populateLoraModelMenu, - getImageCfgScaleSDValue, - setImageCfgScaleSDValue, - refreshSDTab, - displayImageCfgScaleSlider, - requestGetHiResUpscalers, -} diff --git a/utility/tab/settings.js b/utility/tab/settings.js index c74f2d6..859dbb2 100644 --- a/utility/tab/settings.js +++ b/utility/tab/settings.js @@ -1,27 +1,9 @@ const io = require('../io') -function getUseSharpMask() { - const isChecked = document.getElementById('chUseSharpMask').checked - return isChecked -} function setUseSharpMask() { console.warn('setUseSharpMask is not setup') } -function getUseLiveProgressImage() { - const b_live_update = document.getElementById('chLiveProgressImage').checked - return b_live_update -} -function setUseLiveProgressImage(b_live_update) { - document.getElementById('chLiveProgressImage').checked = b_live_update -} - -function getExtensionType() { - return [...document.getElementsByClassName('rbExtensionType')].filter( - (e) => e.checked == true - )[0].value -} - document.getElementById('btnGetDocPath').addEventListener('click', async () => { const docPath = await io.IOFolder.getDocumentFolderNativePath() document.getElementById('tiDocPath').value = docPath @@ -65,8 +47,8 @@ async function changeSdUrl(sd_url) { async function saveSettings() { const settings_tab_settings = { - use_sharp_mask: getUseSharpMask(), - extension_type: getExtensionType(), + use_sharp_mask: settings_tab_ts.store.data.use_sharp_mask, + extension_type: settings_tab_ts.store.data.extension_type, sd_url: getSdUrlHtml(), } @@ -91,15 +73,6 @@ async function loadSettings() { } } -document.getElementById('chUseSharpMask').addEventListener('change', (ev) => { - const isChecked = ev.target.checked - if (isChecked) { - document.getElementById('slMaskBlur').setAttribute('disabled') - } else { - document.getElementById('slMaskBlur').removeAttribute('disabled') - } -}) - document.getElementById('chUseSmartObject').addEventListener('change', (ev) => { const isChecked = ev.target.checked if (isChecked) { @@ -123,15 +96,13 @@ document }) module.exports = { - getUseSharpMask, setUseSharpMask, - getExtensionType, + getSdUrlHtml, setSdUrlHtml, changeSdUrl, loadSettings, saveSettings, - getUseLiveProgressImage, - setUseLiveProgressImage, + getUseOriginalPrompt, } diff --git a/utility/tab/share_tab.js b/utility/tab/share_tab.js deleted file mode 100644 index ec54543..0000000 --- a/utility/tab/share_tab.js +++ /dev/null @@ -1,17 +0,0 @@ -const chLiveProgressImageElements = document.getElementsByClassName( - 'chLiveProgressImageClass' -) - -const default_preview_value = document.getElementById( - 'chLiveProgressImage' -).checked - -chLiveProgressImageElements.forEach((element) => { - element.checked = default_preview_value - element.addEventListener('click', (event) => { - value = element.checked - chLiveProgressImageElements.forEach((element) => { - element.checked = value - }) - }) -}) diff --git a/utility/ui.js b/utility/ui.js deleted file mode 100644 index 9091533..0000000 --- a/utility/ui.js +++ /dev/null @@ -1,282 +0,0 @@ -const html_manip = require('./html_manip') -const presets = require('./presets/preset') -const layer_util = require('../utility/layer') -const psapi = require('../psapi') -const Enum = require('../enum') -const { executeAsModal } = require('photoshop').core - -class UI { - constructor() {} -} - -class UIElement { - constructor() { - this.name - this.html_elem - this.sd_value - } - setValue() {} - getValue() {} -} -function createUIElement(getter, setter) { - let ui_element_obj = new UIElement() - ui_element_obj.getValue = getter - ui_element_obj.setValue = setter - return ui_element_obj -} -class UISettings { - // get and set the settings of the ui. the stable diffusion settings not the human friendly settings - constructor() { - // this.width = new ui.UIElement() - // this.width.getValue = html_manip.getWidth - // this.width.setValue = html_manip.autoFillInWidth - this.width = createUIElement( - html_manip.getWidth, - html_manip.autoFillInWidth - ) - this.height = createUIElement( - html_manip.getHeight, - html_manip.autoFillInHeight - ) - this.steps = createUIElement( - html_manip.getSteps, - html_manip.autoFillInSteps - ) - this.batch_number = createUIElement( - html_manip.getBatchNumber, - html_manip.autoFillInBatchNumber - ) - this.firstphase_width = createUIElement( - html_manip.getHrWidth, - html_manip.autoFillInHRWidth - ) - this.firstphase_height = createUIElement( - html_manip.getHrHeight, - html_manip.autoFillInHRHeight - ) - this.cfg = createUIElement(html_manip.getCFG, html_manip.setCFG) - this.denoising_strength = createUIElement( - html_manip.getDenoisingStrength, - html_manip.autoFillInDenoisingStrength - ) - - this.mask_content = createUIElement( - html_manip.getMaskContent, - html_manip.setMaskContent - ) - this.seed = createUIElement(html_manip.getSeed, html_manip.setSeed) - this.prompt = createUIElement( - html_manip.getPrompt, - html_manip.autoFillInPrompt - ) - this.negative_prompt = createUIElement( - html_manip.getNegativePrompt, - html_manip.autoFillInNegativePrompt - ) - this.mask_blur = createUIElement( - html_manip.getMaskBlur, - html_manip.setMaskBlur - ) - this.mask_expansion = createUIElement( - html_manip.getMaskExpansion, - html_manip.setMaskExpansion - ) - this.samplers = createUIElement( - html_manip.getCheckedSamplerName, - html_manip.autoFillInSampler - ) - - this.uiElements = { - // model: null, - // prompt_shortcut: null, - prompt: this.prompt, - negative_prompt: this.negative_prompt, - // selection_mode: null, - batch_size: this.batch_number, - steps: this.steps, - width: this.width, - height: this.height, - firstphase_width: this.firstphase_width, - firstphase_height: this.firstphase_height, - cfg_scale: this.cfg, - denoising_strength: this.denoising_strength, - // hi_res_denoising_strength:0.7, - mask_blur: this.mask_blur, - mask_expansion: this.mask_expansion, - // inpaint_at_full_res: false, - // hi_res_fix:false, - // inpaint_padding:0, - seed: this.seed, - sampler_index: this.samplers, - mask_content: this.mask_content, - } - } - - autoFillInSettings(settings) { - for (const [name, value] of Object.entries(settings)) { - if (this.uiElements.hasOwnProperty(name) && value) { - //get the values for debugging - const old_value = this.uiElements[name].getValue() - console.log( - '(name,old_value) => newValue:', - name, - old_value, - value - ) - //set the value - this.uiElements[name].setValue(value) - } - } - } - getSettings() { - let settings = {} - for (const [name, ui_element] of Object.entries(this.uiElements)) { - if (ui_element) { - const value = ui_element.getValue() - settings[name] = value - } - } - return settings - } - - saveAsJson(json_file_name, settings) { - for (const [name, value] of Object.entries(settings)) { - if (this.uiElements.hasOwnProperty(name) && value) { - //get the values for debugging - const old_value = this.uiElements[name].getValue() - console.log( - '(name,old_value) => newValue:', - name, - old_value, - value - ) - - //set the value - } - } - } -} -// const ui_settings = new UISettings() - -function loadPreset(ui_settings, preset) { - console.log('preset:', preset) - ui_settings.autoFillInSettings(preset) -} - -function loadLatentNoiseSettings(ui_settings) { - loadPreset(ui_settings, presets.LatentNoiseSettings) -} - -function loadFillSettings(ui_settings) { - loadPreset(ui_settings, presets.FillSettings) -} -function loadOriginalSettings(ui_settings) { - loadPreset(ui_settings, presets.OriginalSettings) -} -async function loadHealBrushSettings(ui_settings) { - document.getElementById('rbModeInpaint').click() - - loadPreset(ui_settings, presets.HealBrushSettings) -} -function loadCustomPreset(ui_settings_obj, custom_preset_settings) { - loadPreset(ui_settings_obj, custom_preset_settings) -} - -function loadCustomPresetsSettings() {} -async function mapCustomPresetsToLoaders(ui_settings_obj) { - const name_to_settings_obj = await presets.getAllCustomPresetsSettings( - Enum.PresetTypeEnum['SDPreset'] - ) - const preset_name_to_loader_obj = {} - for (const [preset_name, preset_settings] of Object.entries( - name_to_settings_obj - )) { - preset_name_to_loader_obj[preset_name] = () => { - loadCustomPreset(ui_settings_obj, preset_settings) - } - } - return preset_name_to_loader_obj -} - -const g_nativePresets = { - fill: loadFillSettings, - original: loadOriginalSettings, - 'latent noise': loadLatentNoiseSettings, - 'Heal Brush': loadHealBrushSettings, -} - -async function getLoadedPresets(ui_settings_obj) { - let customPresets - - customPresets = await mapCustomPresetsToLoaders(ui_settings_obj) - console.log('customPresets: ', customPresets) - let loadedPresets = { - ...g_nativePresets, - ...customPresets, - } - return loadedPresets -} -let g_ui_settings_object = new UISettings() -function getUISettingsObject() { - return g_ui_settings_object -} - -//REFACTOR: move to ui.js -function addPresetMenuItem(preset_title) { - // console.log(model_title,model_name) - const menu_item_element = document.createElement('sp-menu-item') - menu_item_element.className = 'mPresetMenuItem' - menu_item_element.innerHTML = preset_title - - // menu_item_element.addEventListener('select',()=>{ - // preset_func(g_ui_settings) - // }) - return menu_item_element -} -//REFACTOR: move to ui.js -async function populatePresetMenu() { - document.getElementById('mPresetMenu').innerHTML = '' - const divider_elem = document.createElement('sp-menu-divider') - const preset_name = 'Select Smart Preset' - const preset_func = () => {} - const dummy_preset_item = addPresetMenuItem(preset_name, preset_func) - dummy_preset_item.setAttribute('selected', 'selected') - // dummy_preset_item.setAttribute('disabled') - document.getElementById('mPresetMenu').appendChild(dummy_preset_item) - document.getElementById('mPresetMenu').appendChild(divider_elem) - const presets = await getLoadedPresets(g_ui_settings_object) - for ([key, value] of Object.entries(presets)) { - const preset_menu_item = addPresetMenuItem(key, value) - document.getElementById('mPresetMenu').appendChild(preset_menu_item) - } -} - -populatePresetMenu() -//REFACTOR: move to preset_tab.js -document - .getElementById('mPresetMenu') - .addEventListener('change', async (evt) => { - const preset_index = evt.target.selectedIndex - const preset_name = evt.target.options[preset_index].textContent - const presets = await getLoadedPresets(g_ui_settings_object) - if (presets.hasOwnProperty(preset_name)) { - const loader = presets[preset_name] - if (loader.constructor.name === 'AsyncFunction') { - await loader(g_ui_settings_object) - } else { - loader(g_ui_settings_object) - } - } - }) - -module.exports = { - UI, - UIElement, - UISettings, - loadLatentNoiseSettings, - loadFillSettings, - loadHealBrushSettings, - getLoadedPresets, - getUISettingsObject, - populatePresetMenu, -}