mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 01:04:32 +02:00
+6
-2
@@ -1,6 +1,6 @@
|
||||
# Change Log for SD.Next
|
||||
|
||||
## Update for 2023-10-18
|
||||
## Update for 2023-10-20
|
||||
|
||||
Service release addressing all zero-day issues reported so far...
|
||||
|
||||
@@ -12,15 +12,19 @@ Service release addressing all zero-day issues reported so far...
|
||||
- fix handling of relative path for models
|
||||
- fix simple live preview device mismatch
|
||||
- fix batch img2img
|
||||
- fix diffusers dpm++ 2m and 1s samplers
|
||||
- fix diffusers dpm++ 2m, dpm++ 1s, deis samplers
|
||||
- fix new style filename template
|
||||
- fix image name template using model name
|
||||
- fix model path using relative path
|
||||
- fix torch-rocm version detection (thanks @xangelix)
|
||||
- fix chainner upscalers color clipping
|
||||
- force second requirements check on startup
|
||||
- remove lyco, multiple_tqdm
|
||||
- enhance extension compatibility for exensions directly importing codeformers
|
||||
- enhance extension compatibility for exensions directly accessing processing params
|
||||
- clearly mark external themes in ui
|
||||
- new option: *settings -> images -> keep incomplete*
|
||||
can be used to skip vae decode on aborted/skipped/interrupted image generations
|
||||
- update `openvino` (thanks @disty0)
|
||||
- update `typing-extensions`
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
Submodule extensions-builtin/sd-extension-chainner updated: 656293e7bf...f84c381f8e
Submodule extensions-builtin/sd-webui-agent-scheduler updated: 1d623c62fd...2c6d29853e
@@ -77,6 +77,7 @@ function markIfModified(setting_name, value) {
|
||||
tab_nav_indicator.classList.toggle('saved', saved.size > 0);
|
||||
if (changed_items.size > 0) tab_nav_indicator.title += `click to reset ${changed_items.size} unapplied changes in this tab\n`;
|
||||
if (saved.size > 0) tab_nav_indicator.title += `${saved.size} custom values\n${unsaved.size} default values}`;
|
||||
elem.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
|
||||
onAfterUiUpdate(async () => {
|
||||
|
||||
@@ -64,6 +64,8 @@ class ExtraNetwork:
|
||||
|
||||
def activate(p, extra_network_data):
|
||||
"""call activate for extra networks in extra_network_data in specified order, then call activate for all remaining registered networks with an empty argument list"""
|
||||
if extra_network_data is None:
|
||||
return
|
||||
for extra_network_name, extra_network_args in extra_network_data.items():
|
||||
extra_network = extra_network_registry.get(extra_network_name, None)
|
||||
if extra_network is None:
|
||||
@@ -86,6 +88,8 @@ def activate(p, extra_network_data):
|
||||
|
||||
def deactivate(p, extra_network_data):
|
||||
"""call deactivate for extra networks in extra_network_data in specified order, then call deactivate for all remaining registered networks"""
|
||||
if extra_network_data is None:
|
||||
return
|
||||
for extra_network_name in extra_network_data:
|
||||
extra_network = extra_network_registry.get(extra_network_name, None)
|
||||
if extra_network is None:
|
||||
|
||||
+7
-4
@@ -10,7 +10,7 @@ from modules.memstats import memory_stats
|
||||
|
||||
|
||||
def process_batch(p, input_files, input_dir, output_dir, inpaint_mask_dir, args):
|
||||
shared.log.debug(f'batch: {input_dir}|{output_dir}|{inpaint_mask_dir}')
|
||||
shared.log.debug(f'batch: {input_files}|{input_dir}|{output_dir}|{inpaint_mask_dir}')
|
||||
processing.fix_seed(p)
|
||||
if input_files is not None and len(input_files) > 0:
|
||||
image_files = [f.name for f in input_files]
|
||||
@@ -109,8 +109,11 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
|
||||
|
||||
shared.log.debug(f'img2img: id_task={id_task}|mode={mode}|prompt={prompt}|negative_prompt={negative_prompt}|prompt_styles={prompt_styles}|init_img={init_img}|sketch={sketch}|init_img_with_mask={init_img_with_mask}|inpaint_color_sketch={inpaint_color_sketch}|inpaint_color_sketch_orig={inpaint_color_sketch_orig}|init_img_inpaint={init_img_inpaint}|init_mask_inpaint={init_mask_inpaint}|steps={steps}|sampler_index={sampler_index}|latent_index={latent_index}|mask_blur={mask_blur}|mask_alpha={mask_alpha}|inpainting_fill={inpainting_fill}|full_quality={full_quality}|restore_faces={restore_faces}|tiling={tiling}|n_iter={n_iter}|batch_size={batch_size}|cfg_scale={cfg_scale}|image_cfg_scale={image_cfg_scale}|clip_skip={clip_skip}|denoising_strength={denoising_strength}|seed={seed}|subseed{subseed}|subseed_strength={subseed_strength}|seed_resize_from_h={seed_resize_from_h}|seed_resize_from_w={seed_resize_from_w}|selected_scale_tab={selected_scale_tab}|height={height}|width={width}|scale_by={scale_by}|resize_mode={resize_mode}|inpaint_full_res={inpaint_full_res}|inpaint_full_res_padding={inpaint_full_res_padding}|inpainting_mask_invert={inpainting_mask_invert}|img2img_batch_files={img2img_batch_files}|img2img_batch_input_dir={img2img_batch_input_dir}|img2img_batch_output_dir={img2img_batch_output_dir}|img2img_batch_inpaint_mask_dir={img2img_batch_inpaint_mask_dir}|override_settings_texts={override_settings_texts}')
|
||||
|
||||
if init_img is None:
|
||||
shared.log.debug('Init image not set')
|
||||
if mode == 5:
|
||||
if img2img_batch_files is None or len(img2img_batch_files) == 0:
|
||||
shared.log.debug('Init bactch images not set')
|
||||
elif init_img:
|
||||
shared.log.debug('Init image not set')
|
||||
|
||||
if sampler_index is None:
|
||||
sampler_index = 0
|
||||
@@ -202,7 +205,6 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
|
||||
inpainting_mask_invert=inpainting_mask_invert,
|
||||
override_settings=override_settings,
|
||||
)
|
||||
p.is_batch = mode == 5
|
||||
if selected_scale_tab == 1 and resize_mode != 0:
|
||||
p.scale_by = scale_by
|
||||
p.scripts = modules.scripts.scripts_img2img
|
||||
@@ -210,6 +212,7 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
|
||||
p.extra_generation_params['Resize mode'] = resize_mode
|
||||
if mask:
|
||||
p.extra_generation_params["Mask blur"] = mask_blur
|
||||
p.is_batch = mode == 5
|
||||
if p.is_batch:
|
||||
process_batch(p, img2img_batch_files, img2img_batch_input_dir, img2img_batch_output_dir, img2img_batch_inpaint_mask_dir, args)
|
||||
processed = processing.Processed(p, [], p.seed, "")
|
||||
|
||||
@@ -71,15 +71,17 @@ def get_device():
|
||||
core = Core()
|
||||
if os.getenv("OPENVINO_TORCH_BACKEND_DEVICE") is not None:
|
||||
device = os.getenv("OPENVINO_TORCH_BACKEND_DEVICE")
|
||||
elif shared.opts.openvino_multi_gpu:
|
||||
elif shared.opts.openvino_hetero_gpu:
|
||||
device = ""
|
||||
available_devices = core.available_devices
|
||||
available_devices.remove("CPU")
|
||||
if shared.opts.openvino_remove_igpu_from_multi and "GPU.0" in available_devices:
|
||||
if shared.opts.openvino_remove_igpu_from_hetero and "GPU.0" in available_devices:
|
||||
available_devices.remove("GPU.0")
|
||||
for gpu in available_devices:
|
||||
device = f"{device},{gpu}"
|
||||
device = f"MULTI:{device[1:]}"
|
||||
if not shared.opts.openvino_remove_cpu_from_hetero:
|
||||
device = f"{device},CPU"
|
||||
device = f"HETERO:{device[1:]}"
|
||||
elif any(openvino_cpu in cpu_module.lower() for cpu_module in shared.cmd_opts.use_cpu for openvino_cpu in ["openvino", "all"]):
|
||||
device = "CPU"
|
||||
elif shared.cmd_opts.device_id is not None:
|
||||
|
||||
@@ -441,6 +441,10 @@ def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, see
|
||||
|
||||
|
||||
def decode_first_stage(model, x, full_quality=True):
|
||||
if not shared.opts.keep_incomplete and (shared.state.skipped or shared.state.interrupted):
|
||||
shared.log.debug(f'Decode VAE: skipped={shared.state.skipped} interrupted={shared.state.interrupted}')
|
||||
x_sample = torch.zeros((len(x), 3, x.shape[2] * 8, x.shape[3] * 8), dtype=devices.dtype_vae, device=devices.device)
|
||||
return x_sample
|
||||
with devices.autocast(disable = x.dtype==devices.dtype_vae):
|
||||
try:
|
||||
if full_quality:
|
||||
|
||||
+17
-1
@@ -35,6 +35,7 @@ class Script:
|
||||
group = None
|
||||
infotext_fields = None
|
||||
paste_field_names = None
|
||||
section = None
|
||||
|
||||
def title(self):
|
||||
"""this function should return the title of the script. This is what will be displayed in the dropdown menu."""
|
||||
@@ -332,7 +333,6 @@ class ScriptRunner:
|
||||
self.paste_field_names.clear()
|
||||
self.script_load_ctr = 0
|
||||
self.is_img2img = is_img2img
|
||||
|
||||
self.scripts.clear()
|
||||
self.alwayson_scripts.clear()
|
||||
self.selectable_scripts.clear()
|
||||
@@ -355,6 +355,22 @@ class ScriptRunner:
|
||||
except Exception as e:
|
||||
log.error(f'Script initialize: {path} {e}')
|
||||
|
||||
def setup_ui_for_section(self, section, scriptlist=None):
|
||||
if scriptlist is None:
|
||||
scriptlist = self.alwayson_scripts
|
||||
for script in scriptlist:
|
||||
if script.alwayson and script.section != section:
|
||||
continue
|
||||
if script.create_group:
|
||||
with gr.Group(visible=script.alwayson) as group:
|
||||
self.create_script_ui(script)
|
||||
script.group = group
|
||||
else:
|
||||
self.create_script_ui(script)
|
||||
|
||||
def prepare_ui(self):
|
||||
self.inputs = [None]
|
||||
|
||||
def setup_ui(self):
|
||||
import modules.api.models as api_models
|
||||
self.titles = [wrap_call(script.title, script.filename, "title") or f"{script.filename} [error]" for script in self.selectable_scripts]
|
||||
|
||||
@@ -34,6 +34,11 @@ def find_sampler_config(name):
|
||||
return config
|
||||
|
||||
|
||||
def visible_sampler_names():
|
||||
samplers = [x for x in all_samplers if x.name in shared.opts.show_samplers] if len(shared.opts.show_samplers) > 0 else all_samplers
|
||||
return samplers
|
||||
|
||||
|
||||
def create_sampler(name, model):
|
||||
if name == 'Default' and hasattr(model, 'scheduler'):
|
||||
config = {k: v for k, v in model.scheduler.config.items() if not k.startswith('_')}
|
||||
@@ -64,7 +69,7 @@ def create_sampler(name, model):
|
||||
def set_samplers():
|
||||
global samplers # pylint: disable=global-statement
|
||||
global samplers_for_img2img # pylint: disable=global-statement
|
||||
samplers = [x for x in all_samplers if x.name in shared.opts.show_samplers] if len(shared.opts.show_samplers) > 0 else all_samplers
|
||||
samplers = visible_sampler_names()
|
||||
samplers_for_img2img = [x for x in samplers if x.name != "PLMS"]
|
||||
samplers_map.clear()
|
||||
for sampler in all_samplers:
|
||||
|
||||
@@ -97,11 +97,13 @@ class DiffusionSampler:
|
||||
self.config['solver_order'] = shared.opts.schedulers_solver_order
|
||||
if 'predict_x0' in self.config:
|
||||
self.config['predict_x0'] = shared.opts.uni_pc_variant
|
||||
if name == 'DPM++ 2M':
|
||||
self.config['algorithm_type'] = shared.opts.schedulers_dpm_solver
|
||||
if 'beta_start' in self.config and shared.opts.schedulers_beta_start > 0:
|
||||
self.config['beta_start'] = shared.opts.schedulers_beta_start
|
||||
if 'beta_end' in self.config and shared.opts.schedulers_beta_end > 0:
|
||||
self.config['beta_end'] = shared.opts.schedulers_beta_end
|
||||
if name == 'DPM++ 2M':
|
||||
self.config['algorithm_type'] = shared.opts.schedulers_dpm_solver
|
||||
if name == 'DEIS':
|
||||
self.config['algorithm_type'] = 'deis'
|
||||
self.sampler = constructor(**self.config)
|
||||
self.sampler.name = name
|
||||
|
||||
+5
-2
@@ -289,8 +289,9 @@ options_templates.update(options_section(('cuda', "Compute Settings"), {
|
||||
"ipex_optimize": OptionInfo(True if devices.backend == "ipex" else False, "Enable IPEX Optimize for Intel GPUs"),
|
||||
"directml_memory_provider": OptionInfo(default_memory_provider, 'DirectML memory stats provider', gr.Radio, {"choices": memory_providers}),
|
||||
"openvino_disable_model_caching": OptionInfo(False, "OpenVINO disable model caching"),
|
||||
"openvino_multi_gpu": OptionInfo(False, "OpenVINO use Multi GPU"),
|
||||
"openvino_remove_igpu_from_multi": OptionInfo(False, "OpenVINO remove iGPU from Multi GPU"),
|
||||
"openvino_hetero_gpu": OptionInfo(False, "OpenVINO use Hetero Device for single inference with multiple devices"),
|
||||
"openvino_remove_cpu_from_hetero": OptionInfo(False, "OpenVINO remove CPU from Hetero Device"),
|
||||
"openvino_remove_igpu_from_hetero": OptionInfo(False, "OpenVINO remove iGPU from Hetero Device"),
|
||||
}))
|
||||
|
||||
options_templates.update(options_section(('advanced', "Inference Settings"), {
|
||||
@@ -364,6 +365,7 @@ options_templates.update(options_section(('system-paths', "System Paths"), {
|
||||
}))
|
||||
|
||||
options_templates.update(options_section(('saving-images', "Image Options"), {
|
||||
"keep_incomplete": OptionInfo(True, "Keep incomplete images"),
|
||||
"samples_save": OptionInfo(True, "Always save all generated images"),
|
||||
"samples_format": OptionInfo('jpg', 'File format for generated images', gr.Dropdown, {"choices": ["jpg", "png", "webp", "tiff", "jp2"]}),
|
||||
"jpeg_quality": OptionInfo(90, "Quality for saved images", gr.Slider, {"minimum": 1, "maximum": 100, "step": 1}),
|
||||
@@ -425,6 +427,7 @@ options_templates.update(options_section(('ui', "User Interface"), {
|
||||
"gradio_theme": OptionInfo("black-teal", "UI theme", gr.Dropdown, lambda: {"choices": theme.list_themes()}, refresh=theme.refresh_themes),
|
||||
"theme_style": OptionInfo("Auto", "Theme mode", gr.Radio, {"choices": ["Auto", "Dark", "Light"]}),
|
||||
"tooltips": OptionInfo("UI Tooltips", "UI tooltips", gr.Radio, {"choices": ["None", "Browser default", "UI tooltips"], "visible": False}),
|
||||
"gallery_height": OptionInfo("", "Gallery height", gr.Textbox),
|
||||
"compact_view": OptionInfo(False, "Compact view"),
|
||||
"return_grid": OptionInfo(True, "Show grid in results"),
|
||||
"return_mask": OptionInfo(False, "For inpainting, include the greyscale mask in results"),
|
||||
|
||||
+4
-2
@@ -10,7 +10,7 @@ gradio_theme = gr.themes.Base()
|
||||
|
||||
|
||||
def list_builtin_themes():
|
||||
files = [os.path.splitext(f)[0] for f in os.listdir('javascript') if f.endswith('.css')]
|
||||
files = [os.path.splitext(f)[0] for f in os.listdir('javascript') if f.endswith('.css') and f not in ['base.css', 'sdnext.css', 'style.css']]
|
||||
return files
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ def list_themes():
|
||||
builtin = list_builtin_themes()
|
||||
default = ["gradio/default", "gradio/base", "gradio/glass", "gradio/monochrome", "gradio/soft"]
|
||||
external = {x['id'] for x in res if x['status'] == 'RUNNING' and 'test' not in x['id'].lower()}
|
||||
external = [f'huggingface/{x}' for x in external]
|
||||
modules.shared.log.debug(f'Themes: builtin={len(builtin)} default={len(default)} external={len(external)}')
|
||||
themes = sorted(builtin) + sorted(default) + sorted(external, key=str.casefold)
|
||||
return themes
|
||||
@@ -80,8 +81,9 @@ def reload_gradio_theme(theme_name=None):
|
||||
gradio_theme = gr.themes.Soft(**default_font_params)
|
||||
else:
|
||||
try:
|
||||
hf_theme_name = theme_name.replace('huggingface/', '')
|
||||
modules.shared.log.warning('Using 3rd party theme which is not optimized for SD.Next')
|
||||
gradio_theme = gr.themes.ThemeClass.from_hub(theme_name)
|
||||
gradio_theme = gr.themes.ThemeClass.from_hub(hf_theme_name)
|
||||
except Exception:
|
||||
modules.shared.log.error("Theme download error accessing HuggingFace")
|
||||
gradio_theme = gr.themes.Default(**default_font_params)
|
||||
|
||||
+10
-1
@@ -35,6 +35,15 @@ mimetypes.init()
|
||||
mimetypes.add_type('application/javascript', '.js')
|
||||
log = modules.shared.log
|
||||
ui_system_tabs = None
|
||||
switch_values_symbol = symbols.switch
|
||||
detect_image_size_symbol = symbols.detect
|
||||
paste_symbol = symbols.paste
|
||||
clear_prompt_symbol = symbols.clear
|
||||
restore_progress_symbol = symbols.apply
|
||||
folder_symbol = symbols.folder
|
||||
extra_networks_symbol = symbols.networks
|
||||
apply_style_symbol = symbols.apply
|
||||
save_style_symbol = symbols.save
|
||||
|
||||
|
||||
if not cmd_opts.share and not cmd_opts.listen:
|
||||
@@ -353,7 +362,7 @@ def get_value_for_setting(key):
|
||||
|
||||
|
||||
def ordered_ui_categories():
|
||||
return [] # dummy
|
||||
return ['dimensions', 'sampler', 'seed', 'denoising', 'cfg', 'checkboxes', 'accordions', 'override_settings', 'scripts'] # TODO: a1111 compatibility item, not implemented
|
||||
|
||||
|
||||
def create_override_settings_dropdown(tabname, row): # pylint: disable=unused-argument
|
||||
|
||||
@@ -12,6 +12,9 @@ import modules.images
|
||||
import modules.script_callbacks
|
||||
|
||||
|
||||
folder_symbol = symbols.folder
|
||||
|
||||
|
||||
def update_generation_info(generation_info, html_info, img_index):
|
||||
try:
|
||||
generation_info = json.loads(generation_info)
|
||||
@@ -178,7 +181,7 @@ def create_output_panel(tabname):
|
||||
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')
|
||||
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)
|
||||
|
||||
with gr.Column(elem_id=f"{tabname}_footer", elem_classes="gallery_footer"):
|
||||
dummy_component = gr.Label(visible=False)
|
||||
|
||||
@@ -71,3 +71,60 @@ class DropdownEditable(FormComponent, gr.Dropdown):
|
||||
|
||||
def get_block_name(self):
|
||||
return "dropdown"
|
||||
|
||||
|
||||
class InputAccordion(gr.Checkbox):
|
||||
"""A gr.Accordion that can be used as an input - returns True if open, False if closed.
|
||||
Actaully just a hidden checkbox, but creates an accordion that follows and is followed by the state of the checkbox.
|
||||
"""
|
||||
global_index = 0
|
||||
|
||||
def __init__(self, value, **kwargs):
|
||||
self.accordion_id = kwargs.get('elem_id')
|
||||
if self.accordion_id is None:
|
||||
self.accordion_id = f"input-accordion-{InputAccordion.global_index}"
|
||||
InputAccordion.global_index += 1
|
||||
kwargs_checkbox = {**kwargs, "elem_id": f"{self.accordion_id}-checkbox", "visible": False}
|
||||
super().__init__(value, **kwargs_checkbox)
|
||||
self.change(fn=None, _js='function(checked){ inputAccordionChecked("' + self.accordion_id + '", checked); }', inputs=[self])
|
||||
kwargs_accordion = {
|
||||
**kwargs,
|
||||
"elem_id": self.accordion_id,
|
||||
"label": kwargs.get('label', 'Accordion'),
|
||||
"elem_classes": ['input-accordion'],
|
||||
"open": value,
|
||||
}
|
||||
self.accordion = gr.Accordion(**kwargs_accordion)
|
||||
|
||||
def extra(self):
|
||||
"""Allows you to put something into the label of the accordion.
|
||||
Use it like this:
|
||||
```
|
||||
with InputAccordion(False, label="Accordion") as acc:
|
||||
with acc.extra():
|
||||
FormHTML(value="hello", min_width=0)
|
||||
...
|
||||
```
|
||||
"""
|
||||
return gr.Column(elem_id=self.accordion_id + '-extra', elem_classes='input-accordion-extra', min_width=0)
|
||||
|
||||
def __enter__(self):
|
||||
self.accordion.__enter__()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.accordion.__exit__(exc_type, exc_val, exc_tb)
|
||||
|
||||
def get_block_name(self):
|
||||
return "checkbox"
|
||||
|
||||
|
||||
class ResizeHandleRow(gr.Row):
|
||||
"""Same as gr.Row but fits inside gradio forms"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.elem_classes.append("resize-handle-row")
|
||||
|
||||
def get_block_name(self):
|
||||
return "row"
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# TODO: a1111 compatibility item, not used
|
||||
|
||||
import gradio as gr
|
||||
|
||||
from modules import shared, ui_common, ui_components, styles
|
||||
|
||||
styles_edit_symbol = '\U0001f58c\uFE0F' # 🖌️
|
||||
styles_materialize_symbol = '\U0001f4cb' # 📋
|
||||
|
||||
|
||||
def select_style(name):
|
||||
style = shared.prompt_styles.styles.get(name)
|
||||
existing = style is not None
|
||||
empty = not name
|
||||
prompt = style.prompt if style else gr.update()
|
||||
negative_prompt = style.negative_prompt if style else gr.update()
|
||||
return prompt, negative_prompt, gr.update(visible=existing), gr.update(visible=not empty)
|
||||
|
||||
|
||||
def save_style(name, prompt, negative_prompt):
|
||||
if not name:
|
||||
return gr.update(visible=False)
|
||||
style = styles.PromptStyle(name, prompt, negative_prompt)
|
||||
shared.prompt_styles.styles[style.name] = style
|
||||
shared.prompt_styles.save_styles(shared.styles_filename)
|
||||
return gr.update(visible=True)
|
||||
|
||||
|
||||
def delete_style(name):
|
||||
if name == "":
|
||||
return
|
||||
shared.prompt_styles.styles.pop(name, None)
|
||||
shared.prompt_styles.save_styles(shared.styles_filename)
|
||||
return '', '', ''
|
||||
|
||||
|
||||
def materialize_styles(prompt, negative_prompt, styles):
|
||||
prompt = shared.prompt_styles.apply_styles_to_prompt(prompt, styles)
|
||||
negative_prompt = shared.prompt_styles.apply_negative_styles_to_prompt(negative_prompt, styles)
|
||||
return [gr.Textbox.update(value=prompt), gr.Textbox.update(value=negative_prompt), gr.Dropdown.update(value=[])]
|
||||
|
||||
|
||||
def refresh_styles():
|
||||
return gr.update(choices=list(shared.prompt_styles.styles)), gr.update(choices=list(shared.prompt_styles.styles))
|
||||
|
||||
|
||||
class UiPromptStyles:
|
||||
def __init__(self, tabname, main_ui_prompt, main_ui_negative_prompt):
|
||||
self.dropdown = gr.Dropdown(label="Styles", elem_id=f"{tabname}_styles", choices=[style.name for style in shared.prompt_styles.styles.values()], value=[], multiselect=True)
|
||||
|
||||
"""
|
||||
def __init__(self, tabname, main_ui_prompt, main_ui_negative_prompt):
|
||||
self.tabname = tabname
|
||||
|
||||
with gr.Row(elem_id=f"{tabname}_styles_row"):
|
||||
self.dropdown = gr.Dropdown(label="Styles", show_label=False, elem_id=f"{tabname}_styles", choices=list(shared.prompt_styles.styles), value=[], multiselect=True, tooltip="Styles")
|
||||
edit_button = ui_components.ToolButton(value=styles_edit_symbol, elem_id=f"{tabname}_styles_edit_button", tooltip="Edit styles")
|
||||
|
||||
with gr.Box(elem_id=f"{tabname}_styles_dialog", elem_classes="popup-dialog") as styles_dialog:
|
||||
with gr.Row():
|
||||
self.selection = gr.Dropdown(label="Styles", elem_id=f"{tabname}_styles_edit_select", choices=list(shared.prompt_styles.styles), value=[], allow_custom_value=True, info="Styles allow you to add custom text to prompt. Use the {prompt} token in style text, and it will be replaced with user's prompt when applying style. Otherwise, style's text will be added to the end of the prompt.")
|
||||
ui_common.create_refresh_button([self.dropdown, self.selection], shared.prompt_styles.reload, lambda: {"choices": list(shared.prompt_styles.styles)}, f"refresh_{tabname}_styles")
|
||||
self.materialize = ui_components.ToolButton(value=styles_materialize_symbol, elem_id=f"{tabname}_style_apply", tooltip="Apply all selected styles from the style selction dropdown in main UI to the prompt.")
|
||||
|
||||
with gr.Row():
|
||||
self.prompt = gr.Textbox(label="Prompt", show_label=True, elem_id=f"{tabname}_edit_style_prompt", lines=3)
|
||||
|
||||
with gr.Row():
|
||||
self.neg_prompt = gr.Textbox(label="Negative prompt", show_label=True, elem_id=f"{tabname}_edit_style_neg_prompt", lines=3)
|
||||
|
||||
with gr.Row():
|
||||
self.save = gr.Button('Save', variant='primary', elem_id=f'{tabname}_edit_style_save', visible=False)
|
||||
self.delete = gr.Button('Delete', variant='primary', elem_id=f'{tabname}_edit_style_delete', visible=False)
|
||||
self.close = gr.Button('Close', variant='secondary', elem_id=f'{tabname}_edit_style_close')
|
||||
|
||||
self.selection.change(
|
||||
fn=select_style,
|
||||
inputs=[self.selection],
|
||||
outputs=[self.prompt, self.neg_prompt, self.delete, self.save],
|
||||
show_progress=False,
|
||||
)
|
||||
|
||||
self.save.click(
|
||||
fn=save_style,
|
||||
inputs=[self.selection, self.prompt, self.neg_prompt],
|
||||
outputs=[self.delete],
|
||||
show_progress=False,
|
||||
).then(refresh_styles, outputs=[self.dropdown, self.selection], show_progress=False)
|
||||
|
||||
self.delete.click(
|
||||
fn=delete_style,
|
||||
_js='function(name){ if(name == "") return ""; return confirm("Delete style " + name + "?") ? name : ""; }',
|
||||
inputs=[self.selection],
|
||||
outputs=[self.selection, self.prompt, self.neg_prompt],
|
||||
show_progress=False,
|
||||
).then(refresh_styles, outputs=[self.dropdown, self.selection], show_progress=False)
|
||||
|
||||
self.materialize.click(
|
||||
fn=materialize_styles,
|
||||
inputs=[main_ui_prompt, main_ui_negative_prompt, self.dropdown],
|
||||
outputs=[main_ui_prompt, main_ui_negative_prompt, self.dropdown],
|
||||
show_progress=False,
|
||||
).then(fn=None, _js="function(){update_"+tabname+"_tokens(); closePopup();}", show_progress=False)
|
||||
|
||||
ui_common.setup_dialog(button_show=edit_button, dialog=styles_dialog, button_close=self.close)
|
||||
"""
|
||||
Reference in New Issue
Block a user