diff --git a/CHANGELOG.md b/CHANGELOG.md index 7936be0..626ba60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +### 2023-05-22 + +- v23.5.17 +- 컨트롤넷 확장이 있으면 컨트롤넷 스크립트를 활성화함. (컨트롤넷 관련 문제 해결) +- 모든 컴포넌트에 elem_id 설정 +- ui에 버전을 표시함 + + ### 2023-05-19 - v23.5.16 diff --git a/adetailer/__version__.py b/adetailer/__version__.py index ada722c..6b023f2 100644 --- a/adetailer/__version__.py +++ b/adetailer/__version__.py @@ -1 +1 @@ -__version__ = "23.5.16" +__version__ = "23.5.17" diff --git a/adetailer/ui.py b/adetailer/ui.py index 575430a..359523e 100644 --- a/adetailer/ui.py +++ b/adetailer/ui.py @@ -5,7 +5,7 @@ from typing import Any import gradio as gr -from adetailer import AFTER_DETAILER +from adetailer import AFTER_DETAILER, __version__ from adetailer.args import AD_ENABLE, ALL_ARGS, MASK_MERGE_INVERT from controlnet_ext import controlnet_exists, get_cn_inpaint_models @@ -39,6 +39,12 @@ def on_generate_click(state: dict, *values: Any): return state +def elem_id(item_id: str, n: int, is_img2img: bool) -> str: + tap = "img2img" if is_img2img else "txt2img" + suf = suffix(n, "_") + return f"script_{tap}_adetailer_{item_id}{suf}" + + def adui( num_models: int, is_img2img: bool, @@ -48,14 +54,23 @@ def adui( ): states = [] infotext_fields = [] + eid = partial(elem_id, n=0, is_img2img=is_img2img) - with gr.Accordion(AFTER_DETAILER, open=False, elem_id="AD_main_acc"): + with gr.Accordion(AFTER_DETAILER, open=False, elem_id=eid("ad_main_accordion")): with gr.Row(): - ad_enable = gr.Checkbox( - label="Enable ADetailer", - value=False, - visible=True, - ) + with gr.Column(scale=6): + ad_enable = gr.Checkbox( + label="Enable ADetailer", + value=False, + visible=True, + elem_id=eid("ad_enable"), + ) + + with gr.Column(scale=1, min_width=180): + gr.Markdown( + f"v{__version__}", + elem_id=eid("ad_version"), + ) infotext_fields.append((ad_enable, AD_ENABLE.name)) @@ -87,6 +102,7 @@ def one_ui_group( ): w = Widgets() state = gr.State({}) + eid = partial(elem_id, n=n, is_img2img=is_img2img) with gr.Row(): model_choices = model_list if n == 0 else ["None"] + model_list @@ -97,34 +113,45 @@ def one_ui_group( value=model_choices[0], visible=True, type="value", + elem_id=eid("ad_model"), ) with gr.Group(): - with gr.Row(elem_id="AD_toprow_prompt" + suffix(n, "_")): + with gr.Row(elem_id=eid("ad_toprow_prompt")): w.ad_prompt = gr.Textbox( label="ad_prompt" + suffix(n), show_label=False, lines=3, placeholder="ADetailer prompt" + suffix(n), - elem_id="AD_prompt" + suffix(n, "_"), + elem_id=eid("ad_prompt"), ) - with gr.Row(elem_id="AD_toprow_negative_prompt" + suffix(n, "_")): + with gr.Row(elem_id=eid("ad_toprow_negative_prompt")): w.ad_negative_prompt = gr.Textbox( label="ad_negative_prompt" + suffix(n), show_label=False, lines=2, placeholder="ADetailer negative prompt" + suffix(n), - elem_id="AD_negative_prompt" + suffix(n, "_"), + elem_id=eid("ad_negative_prompt"), ) with gr.Group(): - with gr.Accordion("Detection", open=False): - detection(w, n) - with gr.Accordion("Mask Preprocessing", open=False): - mask_preprocessing(w, n) - with gr.Accordion("Inpainting", open=False): - inpainting(w, n) + with gr.Accordion( + "Detection", open=False, elem_id=eid("ad_detection_accordion") + ): + detection(w, n, is_img2img) + + with gr.Accordion( + "Mask Preprocessing", + open=False, + elem_id=eid("ad_mask_preprocessing_accordion"), + ): + mask_preprocessing(w, n, is_img2img) + + with gr.Accordion( + "Inpainting", open=False, elem_id=eid("ad_inpainting_accordion") + ): + inpainting(w, n, is_img2img) with gr.Group(), gr.Row(variant="panel"): cn_inpaint_models = ["None"] + get_cn_inpaint_models() @@ -136,6 +163,7 @@ def one_ui_group( visible=True, type="value", interactive=controlnet_exists, + elem_id=eid("ad_controlnet_model"), ) w.ad_controlnet_weight = gr.Slider( @@ -146,6 +174,7 @@ def one_ui_group( value=1.0, visible=True, interactive=controlnet_exists, + elem_id=eid("ad_controlnet_weight"), ) for attr in ALL_ARGS.attrs: @@ -166,7 +195,9 @@ def one_ui_group( return state, infotext_fields -def detection(w: Widgets, n: int): +def detection(w: Widgets, n: int, is_img2img: bool): + eid = partial(elem_id, n=n, is_img2img=is_img2img) + with gr.Row(): with gr.Column(): w.ad_conf = gr.Slider( @@ -176,6 +207,7 @@ def detection(w: Widgets, n: int): step=1, value=30, visible=True, + elem_id=eid("ad_conf"), ) with gr.Column(variant="compact"): @@ -186,6 +218,7 @@ def detection(w: Widgets, n: int): step=0.001, value=0.0, visible=True, + elem_id=eid("ad_mask_min_ratio"), ) w.ad_mask_max_ratio = gr.Slider( label="Mask max area ratio" + suffix(n), @@ -194,10 +227,13 @@ def detection(w: Widgets, n: int): step=0.001, value=1.0, visible=True, + elem_id=eid("ad_mask_max_ratio"), ) -def mask_preprocessing(w: Widgets, n: int): +def mask_preprocessing(w: Widgets, n: int, is_img2img: bool): + eid = partial(elem_id, n=n, is_img2img=is_img2img) + with gr.Group(): with gr.Row(): with gr.Column(variant="compact"): @@ -208,6 +244,7 @@ def mask_preprocessing(w: Widgets, n: int): step=1, value=0, visible=True, + elem_id=eid("ad_x_offset"), ) w.ad_y_offset = gr.Slider( label="Mask y(↑) offset" + suffix(n), @@ -216,6 +253,7 @@ def mask_preprocessing(w: Widgets, n: int): step=1, value=0, visible=True, + elem_id=eid("ad_y_offset"), ) with gr.Column(variant="compact"): @@ -226,6 +264,7 @@ def mask_preprocessing(w: Widgets, n: int): step=4, value=32, visible=True, + elem_id=eid("ad_dilate_erode"), ) with gr.Row(): @@ -233,10 +272,13 @@ def mask_preprocessing(w: Widgets, n: int): label="Mask merge mode" + suffix(n), choices=MASK_MERGE_INVERT, value="None", + elem_id=eid("ad_mask_merge_invert"), ) -def inpainting(w: Widgets, n: int): +def inpainting(w: Widgets, n: int, is_img2img: bool): + eid = partial(elem_id, n=n, is_img2img=is_img2img) + with gr.Group(): with gr.Row(): w.ad_mask_blur = gr.Slider( @@ -246,6 +288,7 @@ def inpainting(w: Widgets, n: int): step=1, value=4, visible=True, + elem_id=eid("ad_mask_blur"), ) w.ad_denoising_strength = gr.Slider( @@ -255,6 +298,7 @@ def inpainting(w: Widgets, n: int): step=0.01, value=0.4, visible=True, + elem_id=eid("ad_denoising_strength"), ) with gr.Row(): @@ -263,6 +307,7 @@ def inpainting(w: Widgets, n: int): label="Inpaint at full resolution " + suffix(n), value=True, visible=True, + elem_id=eid("ad_inpaint_full_res"), ) w.ad_inpaint_full_res_padding = gr.Slider( label="Inpaint at full resolution padding, pixels " + suffix(n), @@ -271,6 +316,7 @@ def inpainting(w: Widgets, n: int): step=4, value=0, visible=True, + elem_id=eid("ad_inpaint_full_res_padding"), ) w.ad_inpaint_full_res.change( @@ -285,6 +331,7 @@ def inpainting(w: Widgets, n: int): label="Use separate width/height" + suffix(n), value=False, visible=True, + elem_id=eid("ad_use_inpaint_width_height"), ) w.ad_inpaint_width = gr.Slider( @@ -294,6 +341,7 @@ def inpainting(w: Widgets, n: int): step=4, value=512, visible=True, + elem_id=eid("ad_inpaint_width"), ) w.ad_inpaint_height = gr.Slider( @@ -303,6 +351,7 @@ def inpainting(w: Widgets, n: int): step=4, value=512, visible=True, + elem_id=eid("ad_inpaint_height"), ) w.ad_use_inpaint_width_height.change( @@ -318,6 +367,7 @@ def inpainting(w: Widgets, n: int): label="Use separate steps" + suffix(n), value=False, visible=True, + elem_id=eid("ad_use_steps"), ) w.ad_steps = gr.Slider( @@ -327,6 +377,7 @@ def inpainting(w: Widgets, n: int): step=1, value=28, visible=True, + elem_id=eid("ad_steps"), ) w.ad_use_steps.change( @@ -341,6 +392,7 @@ def inpainting(w: Widgets, n: int): label="Use separate CFG scale" + suffix(n), value=False, visible=True, + elem_id=eid("ad_use_cfg_scale"), ) w.ad_cfg_scale = gr.Slider( @@ -350,6 +402,7 @@ def inpainting(w: Widgets, n: int): step=0.5, value=7.0, visible=True, + elem_id=eid("ad_cfg_scale"), ) w.ad_use_cfg_scale.change( @@ -363,4 +416,5 @@ def inpainting(w: Widgets, n: int): w.ad_restore_face = gr.Checkbox( label="Restore faces after ADetailer" + suffix(n), value=False, + elem_id=eid("ad_restore_face"), ) diff --git a/scripts/!adetailer.py b/scripts/!adetailer.py index f9495fa..51f3301 100644 --- a/scripts/!adetailer.py +++ b/scripts/!adetailer.py @@ -47,6 +47,9 @@ no_huggingface = getattr(cmd_opts, "ad_no_huggingface", False) adetailer_dir = Path(models_path, "adetailer") model_mapping = get_models(adetailer_dir, huggingface=not no_huggingface) txt2img_submit_button = img2img_submit_button = None +SCRIPT_DEFAULT = ( + "controlnet,dynamic_prompting,dynamic_thresholding,wildcard_recursive,wildcards" +) if ( not adetailer_dir.exists() @@ -269,21 +272,20 @@ class AfterDetailerScript(scripts.Script): def script_filter(self, p, args: ADetailerArgs): script_runner = copy(p.scripts) script_args = deepcopy(p.script_args) + cn_used = self.disable_controlnet_units(script_args) ad_only_seleted_scripts = opts.data.get("ad_only_seleted_scripts", True) if not ad_only_seleted_scripts: return script_runner, script_args - default = "dynamic_prompting,dynamic_thresholding,wildcards,wildcard_recursive" - ad_script_names = opts.data.get("ad_script_names", default) + ad_script_names = opts.data.get("ad_script_names", SCRIPT_DEFAULT) script_names_set = { name for script_name in ad_script_names.split(",") for name in (script_name, script_name.strip()) } - if args.ad_controlnet_model != "None": - self.disable_controlnet_units(script_args) + if cn_used or args.ad_controlnet_model != "None": script_names_set.add("controlnet") filtered_alwayson = [] @@ -296,12 +298,16 @@ class AfterDetailerScript(scripts.Script): script_runner.alwayson_scripts = filtered_alwayson return script_runner, script_args - def disable_controlnet_units(self, script_args: list[Any]) -> None: + def disable_controlnet_units(self, script_args: list[Any]) -> bool: + cn_used = False for obj in script_args: if "controlnet" in obj.__class__.__name__.lower() and hasattr( obj, "enabled" ): obj.enabled = False + cn_used = True + + return cn_used def get_i2i_p(self, p, args: ADetailerArgs, image): seed, subseed = self.get_seed(p) @@ -562,7 +568,7 @@ def on_ui_settings(): shared.opts.add_option( "ad_script_names", shared.OptionInfo( - default="dynamic_prompting,dynamic_thresholding,wildcards,wildcard_recursive", + default=SCRIPT_DEFAULT, label="Script names to apply to ADetailer (separated by comma)", component=gr.Textbox, component_args=textbox_args,