from modules.ui_components import FormRow, ToolButton from PIL import Image import gradio as gr from scripts.ui_funcs import ( DEFAULT_MAPPING, visualize_mapping, add_row_above, add_row_below, del_row_select, reset_mapping, manual_entry, on_paste, ) from scripts.gr_version import js, is_gradio_4 def couple_UI(script, is_img2img: bool, title: str): m: str = "i2i" if is_img2img else "t2i" preview_js: str = f'() => {{ ForgeCouple.preview("{m}"); }}' with gr.Accordion( label=title, elem_id=f"forge_couple_{m}", open=False, ): with gr.Row(): enable = gr.Checkbox(label="Enable", elem_classes="fc_enable", scale=2) mode = gr.Radio( ["Basic", "Advanced"], label="Region Assignment", value="Basic", scale=3, interactive=(not is_gradio_4), ) separator = gr.Textbox( label="Couple Separator", lines=1, max_lines=1, placeholder="Default: Newline", elem_classes="fc_separator", scale=1, ) with gr.Group() as basic_settings: with gr.Row(): direction = gr.Radio( ["Horizontal", "Vertical"], label="Tile Direction", value="Horizontal", scale=2, ) background = gr.Radio( ["None", "First Line", "Last Line"], label="Global Effect", value="None", scale=3, ) background_weight = gr.Slider( minimum=0.1, maximum=1.0, step=0.1, value=0.5, label="Global Effect Weight", scale=1, ) with gr.Group(visible=False, elem_classes="fc_adv") as adv_settings: with FormRow(elem_classes="fc_map_btns"): new_btn = gr.Button("New Row") ref_btn = gr.Button("Default Mapping") with gr.Group(elem_classes="fc_row_btns"): with gr.Row(): with gr.Column(): new_btn_up = ToolButton( value="\U0001F195", elem_id="fc_up_btn", tooltip="Add a New Row above the Selected Row", ) new_btn_dn = ToolButton( value="\U0001F195", elem_id="fc_dn_btn", tooltip="Add a New Row below the Selected Row", ) del_btn = ToolButton( value="\U0000274C", elem_id="fc_del_btn", tooltip="Delete the Selected Row", ) mapping = gr.Dataframe( label="Mapping", headers=["x", "y", "weight"], datatype="str", row_count=(1, "dynamic"), col_count=(3, "fixed"), interactive=True, type="array", value=DEFAULT_MAPPING, elem_classes="fc_mapping", ) preview_img = gr.Image( value=Image.new("RGB", (1, 1), "black"), image_mode="RGBA", label="Mapping Preview", type="pil", interactive=False, height=512, show_download_button=False, ) with gr.Column(elem_classes="fc_bg_btns"): load_btn = ToolButton( value="\U0001F4C2", elem_id="fc_load_img_btn", tooltip="Load a background image for the mapping visualization", ) if is_img2img: load_i2i_btn = ToolButton( value="\U000023CF", elem_id="fc_load_i2i_img_btn", tooltip="Load the img2img image as the background image", ) clear_btn = ToolButton( value="\U0000274C", elem_id="fc_clear_img_btn", tooltip="Remove the background image", ) preview_btn = gr.Button("Preview Mapping", elem_classes="fc_preview") preview_btn.click(None, **js(preview_js)) preview_res = gr.Textbox( lines=1, max_lines=1, visible=False, interactive=True, elem_classes="fc_preview_res", ) real_preview_btn = gr.Button( visible=False, interactive=True, elem_classes="fc_preview_real", ) real_preview_btn.click( visualize_mapping, [ preview_res, mapping, ], preview_img, ).success(None, **js(f'() => {{ ForgeCouple.updateColors("{m}"); }}')) mapping.select(None, **js(f'() => {{ ForgeCouple.onSelect("{m}"); }}')) mapping.input(None, **js(preview_js)) gr.Markdown( """
""" ) manual_idx = gr.Number( label="Selected Row", value=-1, interactive=True, visible=False, precision=0, elem_classes="fc_index", ) new_btn.click(add_row_below, mapping, mapping, show_progress="hidden").success( None, **js(preview_js) ) new_btn_up.click( add_row_above, [mapping, manual_idx], mapping, show_progress="hidden" ).success(None, **js(preview_js)) new_btn_dn.click( add_row_below, [mapping, manual_idx], mapping, show_progress="hidden" ).success(None, **js(preview_js)) del_btn.click( del_row_select, [mapping, manual_idx], mapping, show_progress="hidden", ).success(None, **js(preview_js)) ref_btn.click(reset_mapping, None, mapping, show_progress="hidden").success( None, **js(preview_js) ) manual_field = gr.Textbox( lines=1, max_lines=1, visible=False, interactive=True, elem_classes="fc_manual_field", ) manual_field.input( manual_entry, [mapping, manual_field, manual_idx], mapping, show_progress="hidden", ).success(None, **js(preview_js)) def on_mode_change(choice): if choice == "Basic": return [ gr.update(visible=True), gr.update(visible=False), ] else: return [ gr.update(visible=False), gr.update(visible=True), ] mode.change(on_mode_change, mode, [basic_settings, adv_settings]) mapping_paste_field = gr.Textbox(visible=False) mapping_paste_field.change( on_paste, mapping_paste_field, mapping, show_progress="hidden" ).success(None, **js(preview_js)) script.paste_field_names = [] script.infotext_fields = [ (enable, "forge_couple"), (direction, "forge_couple_direction"), (background, "forge_couple_background"), (separator, "forge_couple_separator"), (mode, "forge_couple_mode"), (mapping_paste_field, "forge_couple_mapping"), (background_weight, "forge_couple_background_weight"), ] for comp, name in script.infotext_fields: comp.do_not_save_to_config = True script.paste_field_names.append(name) for comp in (manual_idx, manual_field, mapping): comp.do_not_save_to_config = True return [ enable, mode, separator, direction, background, background_weight, mapping, ]