diff --git a/extensions-builtin/sd_forge_controlnet/lib_controlnet/controlnet_ui/controlnet_ui_group.py b/extensions-builtin/sd_forge_controlnet/lib_controlnet/controlnet_ui/controlnet_ui_group.py index a365305e..74b28ae6 100644 --- a/extensions-builtin/sd_forge_controlnet/lib_controlnet/controlnet_ui/controlnet_ui_group.py +++ b/extensions-builtin/sd_forge_controlnet/lib_controlnet/controlnet_ui/controlnet_ui_group.py @@ -315,87 +315,84 @@ class ControlNetUiGroup(object): with gr.Group(visible=not self.is_img2img) as self.image_upload_panel: self.save_detected_map = gr.Checkbox(value=True, visible=False) - with gr.Row(elem_classes=["cnet-image-row"], equal_height=True): - with gr.Group(elem_classes=["cnet-input-image-group"]): - self.image = gr.Image( - source="upload", - brush_radius=20, - mirror_webcam=False, - type="numpy", - tool="sketch", - elem_id=f"{elem_id_tabname}_{tabname}_input_image", - elem_classes=["cnet-image"], - brush_color=shared.opts.img2img_inpaint_mask_brush_color - if hasattr( - shared.opts, "img2img_inpaint_mask_brush_color" - ) - else None, - ) - self.image.preprocess = functools.partial( - svg_preprocess, preprocess=self.image.preprocess - ) - self.openpose_editor.render_upload() - - with gr.Group( - visible=False, elem_classes=["cnet-generated-image-group"] - ) as self.generated_image_group: - self.generated_image = gr.Image( - value=None, - label="Preprocessor Preview", - elem_id=f"{elem_id_tabname}_{tabname}_generated_image", - elem_classes=["cnet-image"], - interactive=True, - height=242, - ) # Gradio's magic number. Only 242 works. - - with gr.Group( - elem_classes=["cnet-generated-image-control-group"] - ): - if self.photopea: - self.photopea.render_child_trigger() - self.openpose_editor.render_edit() - preview_check_elem_id = f"{elem_id_tabname}_{tabname}_controlnet_preprocessor_preview_checkbox" - preview_close_button_js = f"document.querySelector('#{preview_check_elem_id} input[type=\\'checkbox\\']').click();" - gr.HTML( - value=f"""Close""", - visible=True, - elem_classes=["cnet-close-preview"], - ) - - with gr.Group( - visible=False, elem_classes=["cnet-mask-image-group"] - ) as self.mask_image_group: - self.mask_image = gr.Image( - value=None, - label="Upload Mask", - elem_id=f"{elem_id_tabname}_{tabname}_mask_image", - elem_classes=["cnet-mask-image"], - interactive=True, - ) - - with gr.Row(visible=False): - with gr.Tabs(): - with gr.Tab(label="Single Image") as self.upload_tab: - pass - - with gr.Tab(label="Batch") as self.batch_tab: - self.batch_image_dir = gr.Textbox( - label="Input Directory", - placeholder="Leave empty to use img2img batch controlnet input directory", - elem_id=f"{elem_id_tabname}_{tabname}_batch_image_dir", - ) - - with gr.Tab(label="Multi-Inputs") as self.merge_tab: - self.merge_gallery = gr.Gallery( - columns=[4], rows=[2], object_fit="contain", height="auto" - ) - with gr.Row(): - self.merge_upload_button = gr.UploadButton( - "Upload Images", - file_types=["image"], - file_count="multiple", + with gr.Tabs(): + with gr.Tab(label="Single Image") as self.upload_tab: + with gr.Row(elem_classes=["cnet-image-row"], equal_height=True): + with gr.Group(elem_classes=["cnet-input-image-group"]): + self.image = gr.Image( + source="upload", + brush_radius=20, + mirror_webcam=False, + type="numpy", + tool="sketch", + elem_id=f"{elem_id_tabname}_{tabname}_input_image", + elem_classes=["cnet-image"], + brush_color=shared.opts.img2img_inpaint_mask_brush_color + if hasattr( + shared.opts, "img2img_inpaint_mask_brush_color" + ) + else None, ) - self.merge_clear_button = gr.Button("Clear Images") + self.image.preprocess = functools.partial( + svg_preprocess, preprocess=self.image.preprocess + ) + self.openpose_editor.render_upload() + + with gr.Group( + visible=False, elem_classes=["cnet-generated-image-group"] + ) as self.generated_image_group: + self.generated_image = gr.Image( + value=None, + label="Preprocessor Preview", + elem_id=f"{elem_id_tabname}_{tabname}_generated_image", + elem_classes=["cnet-image"], + interactive=True, + height=242, + ) # Gradio's magic number. Only 242 works. + + with gr.Group( + elem_classes=["cnet-generated-image-control-group"] + ): + if self.photopea: + self.photopea.render_child_trigger() + self.openpose_editor.render_edit() + preview_check_elem_id = f"{elem_id_tabname}_{tabname}_controlnet_preprocessor_preview_checkbox" + preview_close_button_js = f"document.querySelector('#{preview_check_elem_id} input[type=\\'checkbox\\']').click();" + gr.HTML( + value=f"""Close""", + visible=True, + elem_classes=["cnet-close-preview"], + ) + + with gr.Group( + visible=False, elem_classes=["cnet-mask-image-group"] + ) as self.mask_image_group: + self.mask_image = gr.Image( + value=None, + label="Upload Mask", + elem_id=f"{elem_id_tabname}_{tabname}_mask_image", + elem_classes=["cnet-mask-image"], + interactive=True, + ) + + with gr.Tab(label="Batch") as self.batch_tab: + self.batch_image_dir = gr.Textbox( + label="Input Directory", + placeholder="Leave empty to use img2img batch controlnet input directory", + elem_id=f"{elem_id_tabname}_{tabname}_batch_image_dir", + ) + + with gr.Tab(label="Multi-Inputs") as self.merge_tab: + self.merge_gallery = gr.Gallery( + columns=[4], rows=[2], object_fit="contain", height="auto" + ) + with gr.Row(): + self.merge_upload_button = gr.UploadButton( + "Upload Images", + file_types=["image"], + file_count="multiple", + ) + self.merge_clear_button = gr.Button("Clear Images") if self.photopea: self.photopea.attach_photopea_output(self.generated_image) diff --git a/extensions-builtin/sd_forge_controlnet/scripts/controlnet.py b/extensions-builtin/sd_forge_controlnet/scripts/controlnet.py index 4f366592..e341a3f7 100644 --- a/extensions-builtin/sd_forge_controlnet/scripts/controlnet.py +++ b/extensions-builtin/sd_forge_controlnet/scripts/controlnet.py @@ -88,11 +88,20 @@ class ControlNetForForgeOfficial(scripts.Script): with gr.Group(elem_id=elem_id_tabname): with gr.Accordion(f"ControlNet Integrated", open=False, elem_id="controlnet"): photopea = Photopea() if not shared.opts.data.get("controlnet_disable_photopea_edit", False) else None - for i in range(max_models): - with gr.Accordion(f"ControlNet Unit {i}", elem_classes=['cnet-unit-tab'], open=i == 0): - group, state = self.uigroup(f"ControlNet-{i}", is_img2img, elem_id_tabname, photopea) + if max_models > 1: + with gr.Tabs(elem_id=f"{elem_id_tabname}_tabs"): + for i in range(max_models): + with gr.Tab(f"ControlNet Unit {i}", + elem_classes=['cnet-unit-tab']): + group, state = self.uigroup(f"ControlNet-{i}", is_img2img, elem_id_tabname, photopea) + ui_groups.append(group) + controls.append(state) + else: + with gr.Column(): + group, state = self.uigroup(f"ControlNet", is_img2img, elem_id_tabname, photopea) ui_groups.append(group) controls.append(state) + for i, ui_group in enumerate(ui_groups): infotext.register_unit(i, ui_group) if shared.opts.data.get("control_net_sync_field_args", True):