dikdimon's picture
Upload extensionsa using SD-Hub extension
7bed60d verified
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(
"""
<p align="center">
<a href="https://github.com/Haoming02/sd-forge-couple#advanced-mapping">[How to Use]</a>
</p>
"""
)
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,
]