diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fd5bd560..d624a94a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log for SD.Next -## Update for 2023-12-14 +## Update for 2023-12-16 *Note*: based on `diffusers==0.25.0.dev0` @@ -57,7 +57,8 @@ - **Other** - **Inpaint** add option `apply_overlay` to control if inpaint result should be applied as overlay or as-is can remove artifacts and hard edges of inpaint area but also remove some details from original - - **chaiNNer** fix NaN issues due to autocast + - **chaiNNer** fix `NaN` issues due to autocast + - **Upscale** increase limit from 4x to 8x given the quality of some upscalers - **Extra Networks** fix sort - disable google fonts check on server startup - fix torchvision/basicsr compatibility diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet index a13bd2feb..102449bf1 160000 --- a/extensions-builtin/sd-webui-controlnet +++ b/extensions-builtin/sd-webui-controlnet @@ -1 +1 @@ -Subproject commit a13bd2febe4fae1184b548504957d19a65425a89 +Subproject commit 102449bf16974baf9fff9a2ecec528755e1ba5e2 diff --git a/javascript/control.js b/javascript/control.js index 4d3afcc9e..090afb11a 100644 --- a/javascript/control.js +++ b/javascript/control.js @@ -1,7 +1,16 @@ -const getControlActiveTab = (...args) => { - const selectedTab = gradioApp().querySelector('#control-tabs > .tab-nav > .selected'); - let activeTab = ''; - if (selectedTab) activeTab = selectedTab.innerText.toLowerCase(); - args.shift(); - return [activeTab, ...args]; -}; +function setupControlUI() { + const tabs = ['input', 'output', 'preview']; + for (const tab of tabs) { + const btn = gradioApp().getElementById(`control-${tab}-button`); + btn.style.cursor = 'pointer'; + btn.onclick = () => { + const t = gradioApp().getElementById(`control-tab-${tab}`); + t.style.display = t.style.display === 'none' ? 'block' : 'none'; + const c = gradioApp().getElementById(`control-${tab}-column`); + c.style.flexGrow = c.style.flexGrow === '0' ? '9' : '0'; + }; + } + log('initControlUI'); +} + +onUiLoaded(setupControlUI); diff --git a/javascript/progressBar.js b/javascript/progressBar.js index 0133d3c1f..85c339f26 100644 --- a/javascript/progressBar.js +++ b/javascript/progressBar.js @@ -40,7 +40,7 @@ function checkPaused(state) { } function setProgress(res) { - const elements = ['txt2img_generate', 'img2img_generate', 'extras_generate']; + const elements = ['txt2img_generate', 'img2img_generate', 'extras_generate', 'control_generate']; const progress = (res?.progress || 0); const job = res?.job || ''; const perc = res && (progress > 0) ? `${Math.round(100.0 * progress)}%` : ''; @@ -57,10 +57,12 @@ function setProgress(res) { document.title = `SD.Next ${perc}`; for (const elId of elements) { const el = document.getElementById(elId); - el.innerText = (res ? `${job} ${perc} ${eta}` : 'Generate'); - el.style.background = res && (progress > 0) - ? `linear-gradient(to right, var(--primary-500) 0%, var(--primary-800) ${perc}, var(--neutral-700) ${perc})` - : 'var(--button-primary-background-fill)'; + if (el) { + el.innerText = (res ? `${job} ${perc} ${eta}` : 'Generate'); + el.style.background = res && (progress > 0) + ? `linear-gradient(to right, var(--primary-500) 0%, var(--primary-800) ${perc}, var(--neutral-700) ${perc})` + : 'var(--button-primary-background-fill)'; + } } } diff --git a/javascript/sdnext.css b/javascript/sdnext.css index afc3f9095..2b3954bc3 100644 --- a/javascript/sdnext.css +++ b/javascript/sdnext.css @@ -70,9 +70,10 @@ button.custom-button{ border-radius: var(--button-large-radius); padding: var(-- .performance { font-size: 0.85em; color: #444; } .performance p { display: inline-block; color: var(--body-text-color-subdued) !important } .performance .time { margin-right: 0; } +#control_gallery { height: 564px; } +#control-inputs { margin-top: 1em; } #txt2img_prompt_container, #img2img_prompt_container, #control_prompt_container { margin-right: var(--layout-gap) } -#txt2img_footer, #img2img_footer, #extras_footer { height: fit-content; } -#txt2img_footer, #img2img_footer { height: fit-content; display: none; } +#txt2img_footer, #img2img_footer, #extras_footer, #control_footer { height: fit-content; display: none; } #txt2img_generate_box, #img2img_generate_box, #control_general_box { gap: 0.5em; flex-wrap: wrap-reverse; height: fit-content; } #txt2img_actions_column, #img2img_actions_column, #control_actions_column { gap: 0.3em; height: fit-content; } #txt2img_generate_box>button, #img2img_generate_box>button, #control_generate_box>button, #txt2img_enqueue, #img2img_enqueue { min-height: 42px; max-height: 42px; line-height: 1em; } @@ -92,7 +93,6 @@ button.custom-button{ border-radius: var(--button-large-radius); padding: var(-- div#extras_scale_to_tab div.form{ flex-direction: row; } #img2img_unused_scale_by_slider { visibility: hidden; width: 0.5em; max-width: 0.5em; min-width: 0.5em; } .inactive{ opacity: 0.5; } -div.dimensions-tools { min-width: 0 !important; max-width: fit-content; flex-direction: row; align-content: center; } div#extras_scale_to_tab div.form{ flex-direction: row; } #mode_img2img .gradio-image>div.fixed-height, #mode_img2img .gradio-image>div.fixed-height img{ height: 480px !important; max-height: 480px !important; min-height: 480px !important; } #img2img_sketch, #img2maskimg, #inpaint_sketch { overflow: overlay !important; resize: auto; background: var(--panel-background-fill); z-index: 5; } @@ -307,7 +307,7 @@ table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-widt #img2img_actions_column {display: flex; min-width: fit-content !important; flex-direction: row;justify-content: space-evenly; align-items: center;} #txt2img_generate_box, #img2img_generate_box, #txt2img_enqueue_wrapper,#img2img_enqueue_wrapper {display: flex;flex-direction: column;height: 4em !important;align-items: stretch;justify-content: space-evenly;} #img2img_interface, #img2img_results, #img2img_footer p {text-wrap: wrap; min-width: 100% !important; max-width: 100% !important;} /* maintain single column for from image operations on larger mobile devices */ - #img2img_sketch, #img2maskimg, #inpaint_sketch {display: flex; alignment-baseline:after-edge !important; overflow: auto !important; resize: none !important; } /* fix inpaint image display being too large for mobile displays */ + #img2img_sketch, #img2maskimg, #inpaint_sketch {display: flex; overflow: auto !important; resize: none !important; } /* fix inpaint image display being too large for mobile displays */ #img2maskimg canvas { width: auto !important; max-height: 100% !important; height: auto !important; } #txt2img_sampler, #txt2img_batch, #txt2img_seed_group, #txt2img_advanced, #txt2img_second_pass, #img2img_sampling_group, #img2img_resize_group, #img2img_batch_group, #img2img_seed_group, #img2img_denoise_group, #img2img_advanced_group { width: 100% !important; } /* fix from text/image UI elements to prevent them from moving around within the UI */ #img2img_resize_group .gradio-radio>div { display: flex; flex-direction: column; width: unset !important; } diff --git a/javascript/ui.js b/javascript/ui.js index e192c5935..845402f99 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -101,6 +101,13 @@ function switch_to_extras(...args) { return Array.from(arguments); } +function switch_to_control(...args) { + const tabs = Array.from(gradioApp().querySelector('#tabs').querySelectorAll('button')); + const btn = tabs.find((el) => el.innerText.toLowerCase() === 'control'); + btn.click(); + return Array.from(arguments); +} + function get_tab_index(tabId) { let res = 0; gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button') @@ -164,6 +171,17 @@ function submit_img2img(...args) { return res; } +function submit_control(...args) { + log('submitControl'); + clearGallery('control'); + const id = randomId(); + requestProgress(id, null, gradioApp().getElementById('control_gallery')); + const res = create_submit_args(args); + res[0] = id; + res[1] = gradioApp().querySelector('#control-tabs > .tab-nav > .selected')?.innerText.toLowerCase() || ''; // selected tab name + return res; +} + function submit_postprocessing(...args) { log('SubmitExtras'); clearGallery('extras'); @@ -211,6 +229,12 @@ function recalculate_prompts_inpaint(...args) { return Array.from(arguments); } +function recalculate_prompts_control(...args) { + recalculatePromptTokens('control_prompt'); + recalculatePromptTokens('control_neg_prompt'); + return Array.from(arguments); +} + function registerDragDrop() { const qs = gradioApp().getElementById('quicksettings'); if (!qs) return; diff --git a/modules/call_queue.py b/modules/call_queue.py index 21f94352d..7da6dddc8 100644 --- a/modules/call_queue.py +++ b/modules/call_queue.py @@ -77,6 +77,7 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False, name=None): vram = {k: -(v//-(1024*1024)) for k, v in shared.mem_mon.read().items()} if vram.get('active_peak', 0) > 0: vram_html = f" |

GPU active {max(vram['active_peak'], vram['reserved_peak'])} MB reserved {vram['reserved']} | used {vram['used']} MB free {vram['free']} MB total {vram['total']} MB | retries {vram['retries']} oom {vram['oom']}

" - res[-1] += f"

Time: {elapsed_text}

{vram_html}
" + if isinstance(res, list): + res[-1] += f"

Time: {elapsed_text}

{vram_html}
" return tuple(res) return f diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index 8dd589772..d26317fc9 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -28,6 +28,7 @@ class ParamBinding: self.source_tabname = source_tabname self.override_settings_component = override_settings_component self.paste_field_names = paste_field_names or [] + debug(f'ParamBinding: {vars(self)}') def reset(): @@ -112,6 +113,8 @@ def create_buttons(tabs_list): name = 'Inpaint' elif name == 'extras': name = 'Process' + elif name == 'control': + name = 'Control' buttons[tab] = gr.Button(f"➠ {name}", elem_id=f"{tab}_tab") return buttons @@ -131,6 +134,9 @@ def register_paste_params_button(binding: ParamBinding): def connect_paste_params_buttons(): binding: ParamBinding for binding in registered_param_bindings: + if binding.tabname not in paste_fields: + debug(f"Not not registered: tab={binding.tabname}") + continue destination_image_component = paste_fields[binding.tabname]["init_img"] fields = paste_fields[binding.tabname]["fields"] override_settings_component = binding.override_settings_component or paste_fields[binding.tabname]["override_settings_component"] diff --git a/modules/processing.py b/modules/processing.py index bb9753e72..3ae023fbe 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -1200,7 +1200,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): - def __init__(self, init_images: list = None, resize_mode: int = 0, resize_name: str = 'None', denoising_strength: float = 0.3, image_cfg_scale: float = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: float = None, refiner_steps: int = 5, refiner_start: float = 0, refiner_prompt: str = '', refiner_negative: str = '', **kwargs): + def __init__(self, init_images: list = None, resize_mode: int = 0, resize_name: str = 'None', denoising_strength: float = 0.3, image_cfg_scale: float = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: float = None, scale_by: float = 1, refiner_steps: int = 5, refiner_start: float = 0, refiner_prompt: str = '', refiner_negative: str = '', **kwargs): super().__init__(**kwargs) self.init_images = init_images self.resize_mode: int = resize_mode @@ -1226,7 +1226,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.refiner_negative = refiner_negative self.enable_hr = None self.is_batch = False - self.scale_by = 1.0 + self.scale_by = scale_by self.sampler = None self.scripts = None self.script_args = [] diff --git a/modules/ui.py b/modules/ui.py index 4100e290b..217e284ec 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -166,16 +166,16 @@ def create_batch_inputs(tab): return batch_count, batch_size -def create_seed_inputs(tab): +def create_seed_inputs(tab, reuse_visible=True): with gr.Accordion(open=False, label="Seed", elem_id=f"{tab}_seed_group", elem_classes=["small-accordion"]): with FormRow(elem_id=f"{tab}_seed_row", variant="compact"): seed = gr.Number(label='Initial seed', value=-1, elem_id=f"{tab}_seed", container=True) random_seed = ToolButton(symbols.random, elem_id=f"{tab}_random_seed", label='Random seed') - reuse_seed = ToolButton(symbols.reuse, elem_id=f"{tab}_reuse_seed", label='Reuse seed') + reuse_seed = ToolButton(symbols.reuse, elem_id=f"{tab}_reuse_seed", label='Reuse seed', visible=reuse_visible) with FormRow(visible=True, elem_id=f"{tab}_subseed_row", variant="compact"): subseed = gr.Number(label='Variation', value=-1, elem_id=f"{tab}_subseed", container=True) random_subseed = ToolButton(symbols.random, elem_id=f"{tab}_random_subseed") - reuse_subseed = ToolButton(symbols.reuse, elem_id=f"{tab}_reuse_subseed") + reuse_subseed = ToolButton(symbols.reuse, elem_id=f"{tab}_reuse_subseed", visible=reuse_visible) subseed_strength = gr.Slider(label='Variation strength', value=0.0, minimum=0, maximum=1, step=0.01, elem_id=f"{tab}_subseed_strength") with FormRow(visible=False): seed_resize_from_w = gr.Slider(minimum=0, maximum=4096, step=8, label="Resize seed from width", value=0, elem_id=f"{tab}_seed_resize_from_w") @@ -215,41 +215,41 @@ def create_advanced_inputs(tab): return cfg_scale, clip_skip, image_cfg_scale, diffusers_guidance_rescale, full_quality, restore_faces, tiling, hdr_clamp, hdr_boundary, hdr_threshold, hdr_center, hdr_channel_shift, hdr_full_shift, hdr_maximize, hdr_max_center, hdr_max_boundry -def create_resize_inputs(tab, images): +def create_resize_inputs(tab, images, time_selector=False, scale_visible=True): dummy_component = gr.Number(visible=False, value=0) with gr.Accordion(open=False, label="Resize", elem_classes=["small-accordion"], elem_id=f"{tab}_resize_group"): with gr.Row(): resize_mode = gr.Radio(label="Resize mode", elem_id=f"{tab}_resize_mode", choices=modules.shared.resize_modes, type="index", value="None") + resize_time = gr.Radio(label="Resize order", elem_id=f"{tab}_resize_order", choices=['Before', 'After'], value="Before", visible=time_selector) with gr.Row(): resize_name = gr.Dropdown(label="Resize method", elem_id=f"{tab}_resize_name", choices=[x.name for x in modules.shared.sd_upscalers], value=opts.upscaler_for_img2img) with FormRow(visible=True) as _resize_group: - with gr.Column(elem_id=f"{tab}_column_size", scale=4): + with gr.Column(elem_id=f"{tab}_column_size"): selected_scale_tab = gr.State(value=0) # pylint: disable=abstract-class-instantiated with gr.Tabs(): with gr.Tab(label="Resize to") as tab_scale_to: with FormRow(): - with gr.Column(elem_id=f"{tab}_column_size", scale=4): - with FormRow(): - width = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=512, elem_id=f"{tab}_width") - height = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=512, elem_id=f"{tab}_height") - with gr.Column(elem_id=f"{tab}_column_dim", scale=1, elem_classes="dimensions-tools"): + with gr.Column(elem_id=f"{tab}_column_size"): with FormRow(): + width = gr.Slider(minimum=64, maximum=8192, step=8, label="Width", value=512, elem_id=f"{tab}_width") + height = gr.Slider(minimum=64, maximum=8192, step=8, label="Height", value=512, elem_id=f"{tab}_height") res_switch_btn = ToolButton(value=symbols.switch, elem_id=f"{tab}_res_switch_btn") res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress=False) detect_image_size_btn = ToolButton(value=symbols.detect, elem_id=f"{tab}_detect_image_size_btn") detect_image_size_btn.click(fn=lambda w, h, _: (w or gr.update(), h or gr.update()), _js="currentImg2imgSourceResolution", inputs=[dummy_component, dummy_component, dummy_component], outputs=[width, height], show_progress=False) with gr.Tab(label="Resize by") as tab_scale_by: - scale_by = gr.Slider(minimum=0.05, maximum=4.0, step=0.05, label="Scale", value=1.0, elem_id=f"{tab}_scale") - with FormRow(): - scale_by_html = FormHTML(resize_from_to_html(0, 0, 0.0), elem_id=f"{tab}_scale_resolution_preview") - gr.Slider(label="Unused", elem_id=f"{tab}_unused_scale_by_slider") - button_update_resize_to = gr.Button(visible=False, elem_id=f"{tab}_update_resize_to") + scale_by = gr.Slider(minimum=0.05, maximum=8.0, step=0.05, label="Scale", value=1.0, elem_id=f"{tab}_scale") + if scale_visible: + with FormRow(): + scale_by_html = FormHTML(resize_from_to_html(0, 0, 0.0), elem_id=f"{tab}_scale_resolution_preview") + gr.Slider(label="Unused", elem_id=f"{tab}_unused_scale_by_slider") + button_update_resize_to = gr.Button(visible=False, elem_id=f"{tab}_update_resize_to") - on_change_args = dict(fn=resize_from_to_html, _js="currentImg2imgSourceResolution", inputs=[dummy_component, dummy_component, scale_by], outputs=scale_by_html, show_progress=False) - scale_by.release(**on_change_args) - button_update_resize_to.click(**on_change_args) + on_change_args = dict(fn=resize_from_to_html, _js="currentImg2imgSourceResolution", inputs=[dummy_component, dummy_component, scale_by], outputs=scale_by_html, show_progress=False) + scale_by.release(**on_change_args) + button_update_resize_to.click(**on_change_args) for component in images: component.change(fn=lambda: None, _js="updateImg2imgResizeToTextAfterChangingImage", inputs=[], outputs=[], show_progress=False) @@ -257,7 +257,7 @@ def create_resize_inputs(tab, images): tab_scale_to.select(fn=lambda: 0, inputs=[], outputs=[selected_scale_tab]) tab_scale_by.select(fn=lambda: 1, inputs=[], outputs=[selected_scale_tab]) # resize_mode.change(fn=lambda x: gr.update(visible=x != 0), inputs=[resize_mode], outputs=[_resize_group]) - return resize_mode, resize_name, width, height, scale_by, selected_scale_tab + return resize_mode, resize_name, width, height, scale_by, selected_scale_tab, resize_time def connect_clear_prompt(button): # pylint: disable=unused-argument @@ -637,7 +637,8 @@ def create_ui(startup_timer = None): *modules.scripts.scripts_txt2img.infotext_fields ] parameters_copypaste.add_paste_fields("txt2img", None, txt2img_paste_fields, override_settings) - parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding(paste_button=txt2img_paste, tabname="txt2img", source_text_component=txt2img_prompt, source_image_component=None)) + txt2img_bindings = parameters_copypaste.ParamBinding(paste_button=txt2img_paste, tabname="txt2img", source_text_component=txt2img_prompt, source_image_component=None) + parameters_copypaste.register_paste_params_button(txt2img_bindings) txt2img_token_button.click(fn=wrap_queued_call(update_token_counter), inputs=[txt2img_prompt, steps], outputs=[txt2img_token_counter]) txt2img_negative_token_button.click(fn=wrap_queued_call(update_token_counter), inputs=[txt2img_negative_prompt, steps], outputs=[txt2img_negative_token_counter]) @@ -731,7 +732,7 @@ def create_ui(startup_timer = None): with FormGroup(elem_classes="settings-accordion"): steps, sampler_index = create_sampler_inputs('img2img') - resize_mode, resize_name, width, height, scale_by, selected_scale_tab = create_resize_inputs('img2img', [init_img, sketch]) + resize_mode, resize_name, width, height, scale_by, selected_scale_tab, _resize_time = create_resize_inputs('img2img', [init_img, sketch]) batch_count, batch_size = create_batch_inputs('img2img') seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w = create_seed_inputs('img2img') @@ -892,9 +893,8 @@ def create_ui(startup_timer = None): ] parameters_copypaste.add_paste_fields("img2img", init_img, img2img_paste_fields, override_settings) parameters_copypaste.add_paste_fields("inpaint", init_img_with_mask, img2img_paste_fields, override_settings) - parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding( - paste_button=img2img_paste, tabname="img2img", source_text_component=img2img_prompt, source_image_component=None, - )) + img2img_bindings = parameters_copypaste.ParamBinding(paste_button=img2img_paste, tabname="img2img", source_text_component=img2img_prompt, source_image_component=None) + parameters_copypaste.register_paste_params_button(img2img_bindings) timer.startup.record("ui-img2img") diff --git a/modules/ui_common.py b/modules/ui_common.py index bd34e475e..368f61730 100644 --- a/modules/ui_common.py +++ b/modules/ui_common.py @@ -195,13 +195,13 @@ def open_folder(result_gallery, gallery_index = 0): subprocess.Popen(["xdg-open", path]) # pylint: disable=consider-using-with -def create_output_panel(tabname): +def create_output_panel(tabname, preview=True): import modules.generation_parameters_copypaste as parameters_copypaste with gr.Column(variant='panel', elem_id=f"{tabname}_results"): with gr.Group(elem_id=f"{tabname}_gallery_container"): # columns are for <576px, <768px, <992px, <1200px, <1400px, >1400px - result_gallery = gr.Gallery(value=[], label='Output', show_label=False, show_download_button=True, allow_preview=True, elem_id=f"{tabname}_gallery", container=False, preview=True, columns=5, object_fit='scale-down', height=shared.opts.gallery_height or None) + result_gallery = gr.Gallery(value=[], label='Output', show_label=False, show_download_button=True, allow_preview=True, elem_id=f"{tabname}_gallery", container=False, preview=preview, columns=5, object_fit='scale-down', height=shared.opts.gallery_height or None) with gr.Column(elem_id=f"{tabname}_footer", elem_classes="gallery_footer"): dummy_component = gr.Label(visible=False) @@ -214,7 +214,7 @@ def create_output_panel(tabname): clip_files.click(fn=None, _js='clip_gallery_urls', inputs=[result_gallery], outputs=[]) save = gr.Button('Save', elem_id=f'save_{tabname}') delete = gr.Button('Delete', elem_id=f'delete_{tabname}') - buttons = parameters_copypaste.create_buttons(["img2img", "inpaint", "extras"]) + buttons = parameters_copypaste.create_buttons(["img2img", "inpaint", "extras", "control"]) download_files = gr.File(None, file_count="multiple", interactive=False, show_label=False, visible=False, elem_id=f'download_files_{tabname}') with gr.Group(): diff --git a/modules/ui_postprocessing.py b/modules/ui_postprocessing.py index de0b71d3f..0fb103859 100644 --- a/modules/ui_postprocessing.py +++ b/modules/ui_postprocessing.py @@ -31,7 +31,7 @@ def create_ui(): extras_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs, placeholder="Leave blank to save images to the default path.", elem_id="extras_batch_output_dir") show_extras_results = gr.Checkbox(label='Show result images', value=True, elem_id="extras_show_extras_results") with gr.Row(): - buttons = parameters_copypaste.create_buttons(["txt2img", "img2img", "inpaint"]) + buttons = parameters_copypaste.create_buttons(["txt2img", "img2img", "inpaint", "control"]) with gr.Row(): save_output = gr.Checkbox(label='Save output', value=True, elem_id="extras_save_output") script_inputs = scripts.scripts_postproc.setup_ui() diff --git a/wiki b/wiki index 240a7339c..faa2defd1 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 240a7339ca1199c7735e279e7ea4cdbac0163ec6 +Subproject commit faa2defd19badfef74a1e4f54b695a68c7651224