mirror of
https://github.com/vladmandic/automatic
synced 2026-09-13 10:08:43 +02:00
feat(ui): filter generated sampler and upscaler lists
This commit is contained in:
@@ -444,7 +444,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg
|
||||
if sampler_index is None:
|
||||
log.warning('Sampler: invalid')
|
||||
sampler_index = 0
|
||||
if hr_sampler_index is None:
|
||||
if hr_sampler_index is None or hr_sampler_index == 'Same as primary':
|
||||
hr_sampler_index = sampler_index
|
||||
if isinstance(extra, list):
|
||||
extra = create_override_settings_dict(extra)
|
||||
|
||||
@@ -537,12 +537,12 @@ class Detailer():
|
||||
renoise_end = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Renoise end', value=shared.opts.detailer_sigma_adjust_max, elem_id=f"{tab}_detailer_renoise_end")
|
||||
sampler_block = None
|
||||
if tab == 'extras': # fold the standalone sampler settings into the detailer accordion; values applied per-job in make_processing, never global opts
|
||||
from modules import sd_samplers
|
||||
sd_samplers.set_samplers()
|
||||
sampler_choices = [s.name for s in sd_samplers.visible_samplers() if s.name != 'Same as primary']
|
||||
from modules import ui_sections
|
||||
sampler_choices, default_value, filtered = ui_sections.sampler_choices()
|
||||
with gr.Accordion('Sampler', open=False, elem_id=f"{tab}_detailer_sampler_accordion", elem_classes=["small-accordion"]):
|
||||
with gr.Row():
|
||||
d_sampler = gr.Dropdown(label='Sampling method', choices=sampler_choices, value='Default', elem_id=f"{tab}_detailer_sampler")
|
||||
ui_sections.create_filter_indicator(tab, 'Sampler', filtered)
|
||||
d_sampler = gr.Dropdown(label='Sampling method', choices=sampler_choices, value=default_value, type='value', elem_id=f"{tab}_detailer_sampler")
|
||||
d_prediction = gr.Dropdown(label='Prediction method', choices=['default', 'epsilon', 'sample', 'v_prediction', 'flow_prediction'], value='default', elem_id=f"{tab}_detailer_prediction")
|
||||
with gr.Row():
|
||||
d_shift = gr.Slider(label='Flow shift', minimum=0, maximum=10, step=0.1, value=shared.opts.schedulers_shift, elem_id=f"{tab}_detailer_shift")
|
||||
|
||||
@@ -296,6 +296,23 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp
|
||||
res.append(v)
|
||||
applied[key] = v
|
||||
else:
|
||||
if key in ('Sampler', 'Hires sampler') and isinstance(v, str):
|
||||
from modules import ui_sections
|
||||
choices, value, _ = ui_sections.sampler_choices(selected=v, same_as_primary=key == 'Hires sampler')
|
||||
res.append(gr.update(choices=choices, value=value))
|
||||
applied[key] = v
|
||||
continue
|
||||
if getattr(output, 'elem_id', '').endswith('_resize_name') and isinstance(v, str):
|
||||
from modules import modelloader, shared, ui_sections
|
||||
modelloader.load_upscalers()
|
||||
choices = [upscaler.name for upscaler in shared.sd_upscalers]
|
||||
if output.elem_id.startswith(('control_after', 'control_mask')):
|
||||
choices = [choice for choice in choices if not choice.lower().startswith('latent')]
|
||||
if v in choices:
|
||||
choices, _ = ui_sections.upscaler_choices(choices, selected=v)
|
||||
res.append(gr.update(choices=choices, value=v))
|
||||
applied[key] = v
|
||||
continue
|
||||
if isinstance(v, str) and v.strip() == '' and key in {'Prompt', 'Negative prompt'}:
|
||||
debug(f'Paste skip empty: "{key}"')
|
||||
res.append(gr.update())
|
||||
|
||||
@@ -193,6 +193,8 @@ def img2img(id_task: str, state: str, mode: int,
|
||||
if sampler_index is None:
|
||||
log.warning('Sampler: invalid')
|
||||
sampler_index = 0
|
||||
if hr_sampler_index is None or hr_sampler_index == 'Same as primary':
|
||||
hr_sampler_index = sampler_index
|
||||
|
||||
mode = int(mode)
|
||||
image = None
|
||||
|
||||
@@ -159,9 +159,11 @@ def images_tensor_to_samples(image, approximation=None, model=None): # pylint: d
|
||||
return x_latent
|
||||
|
||||
|
||||
def get_sampler_name(sampler_index: int | None = None, img: bool = False) -> str:
|
||||
def get_sampler_name(sampler_index: int | str | None = None, img: bool = False) -> str:
|
||||
sampler_index = sampler_index or 0
|
||||
if len(sd_samplers.samplers) > sampler_index:
|
||||
if isinstance(sampler_index, str) and any(sampler.name == sampler_index for sampler in sd_samplers.samplers):
|
||||
sampler_name = sampler_index
|
||||
elif isinstance(sampler_index, int) and 0 <= sampler_index < len(sd_samplers.samplers):
|
||||
sampler_name = sd_samplers.samplers[sampler_index].name
|
||||
else:
|
||||
sampler_name = "Default"
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ def txt2img(id_task, state,
|
||||
if sampler_index is None:
|
||||
log.warning('Sampler: invalid')
|
||||
sampler_index = 0
|
||||
if hr_sampler_index is None:
|
||||
if hr_sampler_index is None or hr_sampler_index == 'Same as primary':
|
||||
hr_sampler_index = sampler_index
|
||||
|
||||
p = processing.StableDiffusionProcessingTxt2Img(
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
"""Helpers for filtering display-only UI choice lists."""
|
||||
|
||||
|
||||
def filter_ui_choices(choices: list[str], preferences: list[str] | None = None, selected: str | None = None) -> tuple[list[str], bool]:
|
||||
"""Return choices selected for display without changing the underlying catalog.
|
||||
|
||||
Empty or stale preferences leave the complete list visible. A current value is
|
||||
always retained so loading a saved workflow cannot silently replace it.
|
||||
"""
|
||||
available = list(dict.fromkeys(choices))
|
||||
preferred = set(preferences or [])
|
||||
filtered = [choice for choice in available if choice in preferred]
|
||||
if not filtered:
|
||||
return available, False
|
||||
if selected in available and selected not in filtered:
|
||||
filtered.append(selected)
|
||||
return filtered, len(filtered) < len(available)
|
||||
@@ -51,6 +51,11 @@ def list_samplers():
|
||||
return modules.sd_samplers.all_samplers
|
||||
|
||||
|
||||
def list_upscalers():
|
||||
from modules import shared # pylint: disable=redefined-outer-name
|
||||
return [upscaler.name for upscaler in shared.sd_upscalers]
|
||||
|
||||
|
||||
def get_openvino_device_list():
|
||||
try:
|
||||
import modules.intel.openvino # pylint: disable=redefined-outer-name
|
||||
@@ -769,6 +774,12 @@ def create_settings(cmd_opts):
|
||||
"disable_all_extensions": OptionInfo("none", "Disable all extensions", gr.Radio, {"choices": ["none", "user", "all"]}),
|
||||
}))
|
||||
|
||||
# --- Sampler Settings ---
|
||||
options_templates.update(options_section(('sampler', "Sampler Settings"), {
|
||||
"show_samplers": OptionInfo([], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers()]}, refresh=list_samplers),
|
||||
"show_upscalers": OptionInfo([], "Show upscalers in user interface", gr.CheckboxGroup, lambda: {"choices": list_upscalers()}, refresh=refresh_upscalers),
|
||||
}))
|
||||
|
||||
# --- Hidden Options ---
|
||||
options_templates.update(
|
||||
options_section(
|
||||
@@ -830,7 +841,6 @@ def create_settings(cmd_opts):
|
||||
"control_move_processor": OptionInfo(False, "Processor move to CPU when complete", gr.Checkbox, {"visible": False}),
|
||||
"control_unload_processor": OptionInfo(False, "Processor unload after use", gr.Checkbox, {"visible": False}),
|
||||
# sampler settings are handled separately
|
||||
"show_samplers": OptionInfo([], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers()], "visible": False}),
|
||||
"eta_noise_seed_delta": OptionInfo(0, "Noise seed delta (eta)", gr.Number, {"precision": 0, "visible": False}),
|
||||
"scheduler_eta": OptionInfo(1.0, "Noise multiplier (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}),
|
||||
"schedulers_solver_order": OptionInfo(0, "Solver order (where", gr.Slider, {"minimum": 0, "maximum": 5, "step": 1, "visible": False}),
|
||||
|
||||
+47
-3
@@ -2,6 +2,7 @@ import gradio as gr
|
||||
from modules import shared, modelloader, ui_symbols, ui_common, sd_samplers
|
||||
from modules.logger import log
|
||||
from modules.ui_components import ToolButton
|
||||
from modules.ui_choices import filter_ui_choices
|
||||
from modules.caption import caption
|
||||
|
||||
|
||||
@@ -213,13 +214,41 @@ def create_color_inputs(tab):
|
||||
return grading_brightness, grading_contrast, grading_saturation, grading_hue, grading_gamma, grading_sharpness, grading_color_temp, grading_shadows, grading_midtones, grading_highlights, grading_clahe_clip, grading_clahe_grid, grading_shadows_tint, grading_highlights_tint, grading_split_tone_balance, grading_vignette, grading_grain, grading_lut_cube_file, grading_lut_strength
|
||||
|
||||
|
||||
def sampler_choices(choices=None, selected='Default', same_as_primary=False):
|
||||
"""Build display-only sampler choices without changing the sampler catalog."""
|
||||
if choices is None:
|
||||
sd_samplers.set_samplers()
|
||||
choices = [sampler for sampler in sd_samplers.samplers if sampler.name != 'Same as primary']
|
||||
names = [choice.name if hasattr(choice, 'name') else choice for choice in choices]
|
||||
visible, filtered = filter_ui_choices(names, shared.opts.show_samplers, selected)
|
||||
if same_as_primary:
|
||||
visible.insert(0, 'Same as primary')
|
||||
value = selected if selected in visible else visible[0]
|
||||
return visible, value, filtered
|
||||
|
||||
|
||||
def upscaler_choices(choices, selected=None):
|
||||
"""Build display-only upscaler choices without changing available upscalers."""
|
||||
return filter_ui_choices(choices, shared.opts.show_upscalers, selected)
|
||||
|
||||
|
||||
def create_filter_indicator(tabname, kind, filtered):
|
||||
if not filtered:
|
||||
return None
|
||||
indicator = gr.Button(value=f'{kind} list filtered', elem_id=f'{tabname}_{kind.lower()}_filter_indicator', elem_classes=['filter-indicator'])
|
||||
indicator.click(fn=None, _js="() => openSettingsSection('sampler')", inputs=[], outputs=[], show_progress='hidden')
|
||||
return indicator
|
||||
|
||||
|
||||
def create_sampler_and_steps_selection(choices, tabname, default_steps:int=20):
|
||||
if choices is None:
|
||||
sd_samplers.set_samplers()
|
||||
choices = [x for x in sd_samplers.samplers if not x.name == 'Same as primary']
|
||||
dropdown_choices, default_value, filtered = sampler_choices(choices)
|
||||
with gr.Row(elem_id=f"{tabname}_sampler_row", elem_classes=['flex-break', 'flexbox']):
|
||||
steps = gr.Slider(minimum=1, maximum=100, step=1, label="Steps", elem_id=f"{tabname}_steps", value=default_steps)
|
||||
sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value='Default', type="index")
|
||||
create_filter_indicator(tabname, 'Sampler', filtered)
|
||||
sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling", choices=dropdown_choices, value=default_value, type="value")
|
||||
return steps, sampler_index
|
||||
|
||||
|
||||
@@ -342,7 +371,9 @@ def create_hires_inputs(tab):
|
||||
with gr.Row(elem_id=f"{tab}_hires_fix_row2"):
|
||||
hr_force = gr.Checkbox(label='Force HiRes', value=False, elem_id=f"{tab}_hr_force")
|
||||
with gr.Row(elem_id=f"{tab}_hires_fix_row2"):
|
||||
hr_sampler_index = gr.Dropdown(label='Refine sampler', elem_id=f"{tab}_sampling_alt", choices=[x.name for x in sd_samplers.samplers], value='Same as primary', type="index")
|
||||
dropdown_choices, _default_value, filtered = sampler_choices(selected='Same as primary', same_as_primary=True)
|
||||
create_filter_indicator(tab, 'Sampler', filtered)
|
||||
hr_sampler_index = gr.Dropdown(label='Refine sampler', elem_id=f"{tab}_sampling_alt", choices=dropdown_choices, value='Same as primary', type="value")
|
||||
with gr.Row(elem_id=f"{tab}_hires_row2"):
|
||||
hr_second_pass_steps = gr.Slider(minimum=0, maximum=99, step=1, label='HiRes steps', elem_id=f"{tab}_steps_alt", value=20)
|
||||
denoising_strength = gr.Slider(minimum=0.0, maximum=0.99, step=0.01, label='Strength', value=0.3, elem_id=f"{tab}_denoising_strength")
|
||||
@@ -365,11 +396,24 @@ def create_resize_inputs(tab, images, accordion=True, latent=False, non_zero=Tru
|
||||
available_upscalers = ['None']
|
||||
if not latent:
|
||||
available_upscalers = [x for x in available_upscalers if not x.lower().startswith('latent')]
|
||||
available_upscalers, filtered = upscaler_choices(available_upscalers, available_upscalers[0])
|
||||
resize_mode = gr.Dropdown(label=f"Mode{prefix}" if non_zero else "Resize mode", elem_id=f"{tab}_resize_mode", choices=shared.resize_modes, type="index", value='Fixed')
|
||||
create_filter_indicator(tab, 'Upscaler', filtered)
|
||||
resize_name = gr.Dropdown(label=f"Method{prefix}" if non_zero else "Resize method", elem_id=f"{tab}_resize_name", choices=available_upscalers, value=available_upscalers[0], visible=True)
|
||||
resize_context_choices = ["Add with forward", "Remove with forward", "Add with backward", "Remove with backward"]
|
||||
resize_context = gr.Dropdown(label=f"Context{prefix}", elem_id=f"{tab}_resize_context", choices=resize_context_choices, value=resize_context_choices[0], visible=False)
|
||||
resize_refresh_btn = ui_common.create_refresh_button(resize_name, modelloader.load_upscalers, lambda: {"choices": modelloader.load_upscalers()}, f'{tab}_upscalers_refresh')
|
||||
|
||||
def refresh_upscaler_choices(selected):
|
||||
modelloader.load_upscalers()
|
||||
refreshed = [upscaler.name for upscaler in shared.sd_upscalers]
|
||||
if not latent:
|
||||
refreshed = [name for name in refreshed if not name.lower().startswith('latent')]
|
||||
refreshed, _ = upscaler_choices(refreshed, selected)
|
||||
value = selected if selected in refreshed else refreshed[0]
|
||||
return gr.update(choices=refreshed, value=value)
|
||||
|
||||
resize_refresh_btn = ToolButton(value=ui_symbols.refresh, elem_id=f'{tab}_upscalers_refresh')
|
||||
resize_refresh_btn.click(fn=refresh_upscaler_choices, inputs=[resize_name], outputs=[resize_name], show_progress='hidden')
|
||||
|
||||
def resize_mode_change(mode):
|
||||
if mode is None or mode == 0:
|
||||
|
||||
@@ -60,8 +60,15 @@ def refresh_upscalers():
|
||||
from modules import shared, modelloader
|
||||
modelloader.load_upscalers() # refresh
|
||||
upscalers = [u for u in shared.sd_upscalers if 'output_type' in inspect.signature(u.scaler.do_upscale).parameters.keys()]
|
||||
upscaler_names = ['None'] + [u.name for u in upscalers]
|
||||
return upscaler_names
|
||||
return ['None'] + [u.name for u in upscalers]
|
||||
|
||||
|
||||
def video_upscaler_choices(selected='None', refresh=False):
|
||||
from modules import shared, modelloader
|
||||
if refresh:
|
||||
modelloader.load_upscalers()
|
||||
upscalers = [upscaler for upscaler in shared.sd_upscalers if 'output_type' in inspect.signature(upscaler.scaler.do_upscale).parameters.keys()]
|
||||
return ui_sections.upscaler_choices(['None'] + [upscaler.name for upscaler in upscalers], selected)
|
||||
|
||||
|
||||
def create_ui_outputs():
|
||||
@@ -96,8 +103,17 @@ def create_ui_outputs():
|
||||
with gr.Row():
|
||||
upscale_scale = gr.Slider(label="Video scale", minimum=1, maximum=4, value=1, step=0.1, elem_id="video_outputs_upscale_scale")
|
||||
with gr.Row():
|
||||
upscale_upscaler = gr.Dropdown(label="Video Upscaler", choices=['None'], value='None', type='value', elem_id="video_outputs_upscale_upscaler")
|
||||
_upscale_upscaler_btn = ui_common.create_refresh_button(upscale_upscaler, refresh_upscalers)
|
||||
upscaler_names, filtered = video_upscaler_choices()
|
||||
ui_sections.create_filter_indicator('video', 'Upscaler', filtered)
|
||||
upscale_upscaler = gr.Dropdown(label="Video Upscaler", choices=upscaler_names, value='None', type='value', elem_id="video_outputs_upscale_upscaler")
|
||||
|
||||
def refresh_video_upscalers(selected):
|
||||
choices, _ = video_upscaler_choices(selected, refresh=True)
|
||||
value = selected if selected in choices else choices[0]
|
||||
return gr.update(choices=choices, value=value)
|
||||
|
||||
_upscale_upscaler_btn = ToolButton(value=ui_symbols.refresh, elem_id='video_upscalers_refresh')
|
||||
_upscale_upscaler_btn.click(fn=refresh_video_upscalers, inputs=[upscale_upscaler], outputs=[upscale_upscaler], show_progress='hidden')
|
||||
return mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb, upscale_scale, upscale_upscaler
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
"""CPU-only regression coverage for display-only sampler and upscaler filters."""
|
||||
|
||||
import pathlib
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
|
||||
from modules.ui_choices import filter_ui_choices
|
||||
|
||||
|
||||
class TestUiChoiceFilters(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.choices = ['Default', 'Euler', 'DPM++ 2M', 'Lanczos']
|
||||
|
||||
def test_empty_preferences_leave_choices_unfiltered(self):
|
||||
visible, filtered = filter_ui_choices(self.choices, [])
|
||||
self.assertEqual(visible, self.choices)
|
||||
self.assertFalse(filtered)
|
||||
|
||||
def test_preferences_filter_only_current_catalog_choices(self):
|
||||
visible, filtered = filter_ui_choices(self.choices, ['Euler', 'Lanczos'])
|
||||
self.assertEqual(visible, ['Euler', 'Lanczos'])
|
||||
self.assertTrue(filtered)
|
||||
|
||||
def test_stale_preferences_do_not_hide_the_catalog(self):
|
||||
visible, filtered = filter_ui_choices(self.choices, ['Removed sampler'])
|
||||
self.assertEqual(visible, self.choices)
|
||||
self.assertFalse(filtered)
|
||||
|
||||
def test_saved_selection_remains_available_when_not_preferred(self):
|
||||
visible, filtered = filter_ui_choices(self.choices, ['Euler'], selected='DPM++ 2M')
|
||||
self.assertEqual(visible, ['Euler', 'DPM++ 2M'])
|
||||
self.assertTrue(filtered)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Vendored
+1
@@ -141,6 +141,7 @@ declare global {
|
||||
onUiUpdate?: (callback: () => void) => void; // ui/script.ts
|
||||
timer?: (name: string, elapsed: number) => Promise<void>; // ui/timers.ts
|
||||
markIfModified?: (setting_name: string, value: unknown) => void; // ui/settings.ts
|
||||
openSettingsSection?: (sectionId: string) => void; // ui/settings.ts
|
||||
appendContextMenuOption?: (targetElementSelector: string, entryName: string, entryFunction: () => void, primary?: boolean) => string; // ui/contextMenus.ts
|
||||
generateForever?: (genbuttonid: string) => void; // ui/contextMenus.ts
|
||||
removeContextMenuOption?: (id: string) => void; // ui/contextMenus.ts
|
||||
|
||||
@@ -1275,6 +1275,8 @@
|
||||
],
|
||||
"s": [
|
||||
{"id":"txt2img_sampler","label":"Sampler","localized":"","hint":"Settings related to sampler and seed selection and configuration. Samplers guide the process of turning noise into an image over multiple steps.","ui":"txt2img"},
|
||||
{"id":"","label":"Sampler list filtered","localized":"","hint":"This list only shows samplers selected in <b><i>Sampler Settings</i></b>. Select to open settings.","ui":"txt2img"},
|
||||
{"id":"","label":"Sampler Settings","localized":"","hint":"Preferences for sampler and upscaler lists.","ui":"settings_sampler"},
|
||||
{"id":"","label":"Scripts","localized":"","hint":"Enable additional features by using selected scripts during generate process","ui":"txt2img"},
|
||||
{"id":"","label":"Scale","localized":"","hint":"Resize image to target scale. If resize fixed width/height are set this option is ignored","ui":"txt2img"},
|
||||
{"id":"xy_grid_swap_axes_button","label":"Swap X/Y","localized":"","hint":"","ui":"script_xyz_grid_script"},
|
||||
@@ -1325,6 +1327,8 @@
|
||||
{"id":"","label":"Server log","localized":"","hint":""},
|
||||
{"id":"","label":"Steps","localized":"","hint":"How many times to improve the generated image iteratively; higher values take longer; very low values can produce bad results","ui":"txt2img"},
|
||||
{"id":"","label":"Sampling method","localized":"","hint":"Which algorithm to use to produce the image","ui":"txt2img"},
|
||||
{"id":"","label":"Show samplers in user interface","localized":"","hint":"Select favorite samplers to show in generated dropdowns. Leave empty to show all samplers. Restart the UI after changing this setting.","ui":"settings_sampler"},
|
||||
{"id":"","label":"Show upscalers in user interface","localized":"","hint":"Select favorite upscalers to show in generated dropdowns. Leave empty to show all upscalers. Restart the UI after changing this setting.","ui":"settings_sampler"},
|
||||
{"id":"","label":"Sigma method","localized":"","hint":"Controls how noise levels (sigmas) are distributed across diffusion steps.<br><b>Default</b>: use the scheduler's built-in sigma method.<br><b>Karras</b>: smoother schedule that emphasizes later steps where fine details emerge; generally higher quality with fewer steps.<br><b>Betas</b>: derive sigmas directly from the model's beta schedule (classic <i>DDPM</i> behavior).<br><b>Exponential</b>: exponential decay of noise across steps; aggressive denoising early, slower refinement later.<br><b>Lambdas</b>: Lu's lambdas method from the <i>DPM-Solver</i> paper, specific to the <b>DPM++</b> family.<br><b>Flowmatch</b>: sigma schedule tuned for flow-matching models (<i>Flux</i>, <i>SD3</i>, video models).","ui":"txt2img"},
|
||||
{"id":"","label":"Sigma adjust","localized":"","hint":"Multiplier applied to the sampler's step size during the active timestep window. (Sigma is the amount of noise the sampler removes at each step.)<br>Values below 1.0 shrink the step for smoother, more conservative denoising. Values above 1.0 enlarge it for sharper, more aggressive sampling.<br><br>Default 1.0 disables the adjustment entirely. Use Adjust start and Adjust end to define the timestep range where the multiplier takes effect.","ui":"txt2img"},
|
||||
{"id":"","label":"Sampler order","localized":"","hint":"Overrides the solver order of the active sampler when set above 0.<br>Higher orders use more historical steps per update for greater stability and accuracy at the cost of extra compute. Lower orders are faster but noisier.<br><br>Default 0 leaves each sampler at its built-in order. Many samplers in the dropdown already encode their order in the name (e.g. <b>DPM++ 2M</b> is order 2, <b>DPM++ 3M</b> is order 3, <b>DPM++ 2M SDE</b> is order 2).<br><br>Within a sampler family, the named variants differ ONLY by this value, so picking <b>DPM++ 2M</b> with the slider at 3 produces a scheduler that is functionally identical to picking <b>DPM++ 3M</b> with the slider at 0. The same equivalence holds across the rest of the <b>DPM++</b> multistep family (including the SDE and Inverse variants) and across the <b>ER-SDE</b> family.<br><br>Samplers without a configurable solver order (<b>DDIM</b>, plain <b>Euler</b>, ancestrals, etc.) ignore this slider entirely.","ui":"txt2img"},
|
||||
@@ -1577,6 +1581,7 @@
|
||||
{"id":"component-5611","label":"Update all","localized":"","hint":"","ui":"models_metadata_tab"},
|
||||
{"id":"","label":"UNet/DiT","localized":"","hint":""},
|
||||
{"id":"","label":"Upscale","localized":"","hint":"Upscale image","ui":"extras"},
|
||||
{"id":"","label":"Upscaler list filtered","localized":"","hint":"This list only shows upscalers selected in <b><i>Sampler Settings</i></b>. Select to open settings.","ui":"txt2img"},
|
||||
{"id":"","label":"UI Tabs","localized":"","hint":"","ui":"settings_ui"},
|
||||
{"id":"","label":"Upscaling","localized":"","hint":"","ui":"settings_postprocessing"},
|
||||
{"id":"","label":"Use segmentation","localized":"","hint":"Use the model's pixel-precise segmentation mask as the inpaint mask instead of the rectangular bounding box.<br>Tighter mask means less unintended change around the detection (e.g., the inpaint stays on the face, not on the hair or background behind it). Better blending and smaller seams.<br><br>Requires a segmentation-capable model (filename usually contains <code>-seg</code>). Bounding-box-only models silently fall back to the rectangle.<br>Default off.","ui":"txt2img"},
|
||||
|
||||
@@ -78,6 +78,17 @@ function showAllSettings() {
|
||||
});
|
||||
}
|
||||
|
||||
function openSettingsSection(sectionId: string) {
|
||||
const settingsTab = gradioApp().getElementById('tab_settings');
|
||||
const settingsButton = settingsTab ? gradioApp().querySelector(`button[aria-controls="${settingsTab.id}"]`) : null;
|
||||
settingsButton?.click();
|
||||
const section = gradioApp().getElementById(`settings_section_tab_${sectionId}`);
|
||||
const sectionButton = section ? gradioApp().querySelector(`button[aria-controls="${section.id}"]`) : null;
|
||||
sectionButton?.click();
|
||||
section?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
window.openSettingsSection = openSettingsSection;
|
||||
|
||||
function markIfModified(setting_name, value) {
|
||||
if (!opts_metadata[setting_name]) return;
|
||||
const elem = gradioApp().getElementById(`modification_indicator_${setting_name}`);
|
||||
|
||||
Reference in New Issue
Block a user