读懂这个bpy的3d建模插件源码

下面代码的核心部分:
本地模式diffusion. 先跑1214行. 先走execute,生成图片之后.走1265行. def execute_operator_in_main_thread(): 这个函数!!!!!
这个函数可以把2d 变成3d 贴图.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

bl_info = {
    "name" : "AutoPainter AI",
    "author" : "Blender Procedural", 
    "description" : "AI-Powered Texturing for 3D Models",
    "blender" : (4, 2, 0),
    "version" : (1, 0, 0),
    "location" : "",
    "warning" : "",
    "doc_url": "",
    "tracker_url": "", 
    "category" : "3D View" 
}


import bpy
import bpy.utils.previews
import os
import base64
from mathutils import Vector
import threading
import random
import importlib
import subprocess
import shutil


addon_keymaps = {}
_icons = None
controlnet = {'sna_stable_models_list': [], 'sna_stable_models_list_enum': [], 'sna_controlnet_models_list': [], 'sna_controlnet_normal_models_list_enum': [], 'sna_controlnet_depth_models_list_enum': [], }
layers = {'sna_bakepaths': [], }


def load_preview_icon(path):
    global _icons
    if not path in _icons:
        if os.path.exists(path):
            _icons.load(path, path, "IMAGE")
        else:
            return 0
    return _icons[path].icon_id


def sna_update_sna_outputpath_C4FC1(self, context):
    sna_updated_prop = self.sna_outputpath
    if os.path.exists(sna_updated_prop):
        image_6CE75 = bpy.data.images.load(filepath=sna_updated_prop, )
        bpy.context.scene.sna_outputimage = image_6CE75


def random_integer(min, max, seed):
    random.seed(seed)
    return random.randint(int(min), int(max))


def sna_update_sna_statusfloat_64985(self, context):
    sna_updated_prop = self.sna_statusfloat


def sna_update_sna_error_28FD9(self, context):
    sna_updated_prop = self.sna_error
    if bpy.context and bpy.context.screen:
        for a in bpy.context.screen.areas:
            a.tag_redraw()


_item_map = dict()


def make_enum_item(_id, name, descr, preview_id, uid):
    lookup = str(_id)+"\0"+str(name)+"\0"+str(descr)+"\0"+str(preview_id)+"\0"+str(uid)
    if not lookup in _item_map:
        _item_map[lookup] = (_id, name, descr, preview_id, uid)
    return _item_map[lookup]


def property_exists(prop_path, glob, loc):
    try:
        eval(prop_path, glob, loc)
        return True
    except:
        return False


def sna_update_sna_progress_step_D1001(self, context):
    sna_updated_prop = self.sna_progress_step
    print(str(sna_updated_prop))


def sna_update_sna_depthpath_2B6F0(self, context):
    sna_updated_prop = self.sna_depthpath
    if bpy.context and bpy.context.screen:
        for a in bpy.context.screen.areas:
            a.tag_redraw()
    if os.path.exists(sna_updated_prop):
        if bpy.context and bpy.context.screen:
            for a in bpy.context.screen.areas:
                a.tag_redraw()
        image_F62CC = bpy.data.images.load(filepath=sna_updated_prop, )
        bpy.context.scene.sna_depthimage = image_F62CC
        if os.path.exists(bpy.context.scene.sna_normalpath):
            image_ABA63 = bpy.data.images.load(filepath=bpy.context.scene.sna_normalpath, )
            bpy.context.scene.sna_normalimage = image_ABA63


def get_id_preview_id(data):
    if hasattr(data, "preview"):
        if not data.preview:
            data.preview_ensure()
        if hasattr(data.preview, "icon_id"):
            return data.preview.icon_id
    return 0


class SNA_PT_AUTOPAINTER_AI_0A434(bpy.types.Panel):
    bl_label = 'AutoPainter AI'
    bl_idname = 'SNA_PT_AUTOPAINTER_AI_0A434'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = ''
    bl_category = 'AutoPainter AI'
    bl_order = 0
    bl_ui_units_x=0

    @classmethod
    def poll(cls, context):
        return not (False)

    def draw_header(self, context):
        layout = self.layout
        op = layout.operator('sn.dummy_button_operator', text='', icon_value=load_preview_icon(os.path.join(os.path.dirname(__file__), 'assets', 'image (13) (1).png')), emboss=True, depress=False)
        layout.separator(factor=0.0)

    def draw(self, context):
        layout = self.layout


class SNA_OT_Aovbake_Ad980(bpy.types.Operator):# 进行烘焙,设置光照等.
    bl_idname = "sna.aovbake_ad980"
    bl_label = "aovbake"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('Please save your Blender file before running the script.')
        return not ('' == bpy.data.filepath)

    def execute(self, context):
        if ('' == bpy.data.filepath):
            self.report({'ERROR'}, message='Please save your Blender file before running the script.')
        else:
            if bpy.context.view_layer.objects.active.type == 'MESH':
                bpy.data.scenes['Scene'].render.film_transparent = True
                bpy.data.scenes['Scene'].render.engine = 'CYCLES'
                bpy.data.scenes['Scene'].view_layers['ViewLayer'].use_pass_z = True
                bpy.data.scenes['Scene'].cycles.samples = 16
                bpy.data.scenes['Scene'].render.resolution_x = 1024
                bpy.data.scenes['Scene'].render.resolution_y = 1024
                bpy.data.scenes['Scene'].view_layers['ViewLayer'].use_pass_normal = True
                bpy.context.scene.sna_activeobject = bpy.context.view_layer.objects.active
                if property_exists("bpy.data.materials['Normal_Mat']", globals(), locals()):
                    pass
                else:
                    before_data = list(bpy.data.materials)
                    bpy.ops.wm.append(directory=os.path.join(os.path.dirname(__file__), 'assets', 'Materials.blend') + r'\Material', filename='Normal_Mat', link=False)
                    new_data = list(filter(lambda d: not d in before_data, list(bpy.data.materials)))
                    appended_99020 = None if not new_data else new_data[0]
                bpy.data.scenes['Scene'].use_nodes = True
                normal_material = bpy.data.materials['Normal_Mat']
                import math

                def show_message_box(message="", title="Message", icon='INFO'):
                    """Shows a pop-up message in Blender."""

                    def draw(self, context):
                        self.layout.label(text=message)
                    bpy.context.window_manager.popup_menu(draw, title=title, icon=icon)

                def create_camera_for_object(obj):
                    if obj.type != 'MESH':
                        show_message_box("Selected object must be a mesh.", "Error")
                        return None
                    bpy.ops.object.camera_add()
                    cam = bpy.context.object
                    cam.name = "ObjectCamera"
                    bpy.context.scene.camera = cam
                    bpy.context.scene.sna_bakecam = bpy.context.scene.camera
                    bbox_corners = [obj.matrix_world @ Vector(corner) for corner in obj.bound_box]
                    min_x = min(corner.x for corner in bbox_corners)
                    max_x = max(corner.x for corner in bbox_corners)
                    min_y = min(corner.y for corner in bbox_corners)
                    max_y = max(corner.y for corner in bbox_corners)
                    min_z = min(corner.z for corner in bbox_corners)
                    max_z = max(corner.z for corner in bbox_corners)
                    center = (Vector((min_x + max_x, min_y + max_y, min_z + max_z)) / 2).to_3d()
                    size = max(max_x - min_x, max_y - min_y, max_z - min_z) * 1.5
                    cam.location = center + Vector((0, -size, 0))
                    cam.data.type = 'ORTHO'
                    cam.data.ortho_scale = size
                    cam.rotation_euler = (math.radians(90), 0, 0)
                    bpy.context.scene.sna_activeobject.select_set(state=True)
                    bpy.ops.view3d.camera_to_view_selected()
                    return cam

                def setup_compositing_for_depth():
                    bpy.context.scene.use_nodes = True
                    tree = bpy.context.scene.node_tree
                    nodes = tree.nodes
                    # Remove all existing nodes
                    for node in nodes:
                        nodes.remove(node)
                    # Add required nodes
                    render_layers_node = nodes.new(type='CompositorNodeRLayers')
                    render_layers_node.location = (0, 0)
                    normalize_node = nodes.new(type='CompositorNodeNormalize')
                    normalize_node.location = (200, 0)
                    alpha_math_node = nodes.new(type='CompositorNodeMath')
                    alpha_math_node.location = (400, 0)
                    alpha_math_node.operation = 'SUBTRACT'
                    composite_node = nodes.new(type='CompositorNodeComposite')
                    composite_node.location = (600, 0)
                    # Link nodes
                    tree.links.new(render_layers_node.outputs['Depth'], normalize_node.inputs[0])
                    tree.links.new(normalize_node.outputs[0], alpha_math_node.inputs[1])  # Connect Depth output to input 1 of SUBTRACT node
                    tree.links.new(render_layers_node.outputs['Alpha'], alpha_math_node.inputs[0])  # Connect Alpha output to input 0 of SUBTRACT node
                    tree.links.new(alpha_math_node.outputs[0], composite_node.inputs[0])  # Connect the output of the SUBTRACT node to the Composite node

                def render_depth_map(output_filename: str):
                    blend_file_path = bpy.data.filepath
                    if not blend_file_path:
                        show_message_box("Please save your Blender file before running the script.", "Error")
                        return
                    output_dir = os.path.join(os.path.dirname(blend_file_path), 'output')
                    os.makedirs(output_dir, exist_ok=True)
                    # Define the temporary output path
                    temp_path = os.path.join(output_dir, "depth_map_temp.png")
                    final_path = os.path.join(output_dir, output_filename)
                    setup_compositing_for_depth()
                    bpy.context.scene.render.filepath = temp_path
                    bpy.ops.render.render(write_still=True)
                    # Rename the temporary file to the final filename
                    if os.path.exists(temp_path):
                        if os.path.exists(final_path):
                            os.remove(final_path)  # Remove the existing file if it exists
                        os.rename(temp_path, final_path)
                        bpy.context.scene.sna_depthpath = final_path
                    show_message_box(f"Depth map rendered and saved to {final_path}", "Success")
                    print(f"Depth map rendered and saved to {final_path}")
                # Timer function to render the depth map

                def render_depth_map_timer():
                    render_depth_map("depth_map.png")
                    # After rendering is done, invoke the operator
                    bpy.app.timers.register(execute_operator_in_main_thread)
                    return None  # Stops the timer

                def execute_operator_in_main_thread():
                    """Execute the operator in the correct context after depth map rendering."""
                    for window in bpy.context.window_manager.windows:
                        screen = window.screen
                        for area in screen.areas:
                            if area.type == 'VIEW_3D':  # Ensure you're in the right context, like VIEW_3D
                                with bpy.context.temp_override(window=window, area=area):
                                    bpy.ops.sna.combine_d06e8('INVOKE_DEFAULT')
                                    return
                # Usage example

                def main():
                    obj = bpy.context.active_object
                    if obj is None:
                        show_message_box("No active object selected.", "Error")
                        return
                    create_camera_for_object(obj)
                    # Register the depth map render function as a timer to ensure it runs after everything is set up
                    bpy.app.timers.register(render_depth_map_timer)
                # Example usage
                main()
                bpy.context.scene.sna_activeobject.select_set(state=True, )
                bpy.context.view_layer.objects.active = bpy.context.scene.sna_activeobject
                bpy.data.scenes['Scene'].use_nodes = False
                normal_material = bpy.data.materials['Normal_Mat']

                def apply_normal_material(obj):
                    if "Normal_Mat" in bpy.data.materials:
                        mat = bpy.data.materials["Normal_Mat"]
                        if obj.data.materials:
                            obj.data.materials[0] = mat
                        else:
                            obj.data.materials.append(mat)
                    else:
                        show_message_box("Material 'Normal_Mat' not found.", "Warning")

                def show_message_box(message="", title="Message", icon='INFO'):
                    """Shows a pop-up message in Blender."""

                    def draw(self, context):
                        self.layout.label(text=message)
                    bpy.context.window_manager.popup_menu(draw, title=title, icon=icon)

                def render_normal(render_filename: str):
                    blend_file_path = bpy.data.filepath
                    if not blend_file_path:
                        show_message_box("Please save your Blender file before running the script.", "Error")
                        return
                    output_dir = os.path.join(os.path.dirname(blend_file_path), 'output')
                    os.makedirs(output_dir, exist_ok=True)
                    render_path = os.path.join(output_dir, render_filename)
                    normal_scene = bpy.context.scene.copy()
                    normal_scene.name = "Render_normal"
                    normal_scene.render.engine = 'CYCLES'
                    normal_scene.render.image_settings.file_format = 'PNG'
                    normal_scene.render.image_settings.color_mode = 'RGB'
                    normal_scene.render.image_settings.color_depth = '8'
                    normal_scene.display_settings.display_device = 'sRGB'
                    normal_scene.view_settings.view_transform = 'Standard'
                    bpy.data.scenes['Render_normal'].cycles.samples = 16
                    normal_scene.render.filepath = render_path
                    world = bpy.data.worlds.new("World_normal")
                    normal_scene.world = world
                    world.use_nodes = True
                    world.node_tree.nodes["Background"].inputs[0].default_value = (0.5, 0.5, 1.0, 1.0)
                    normal_material = bpy.data.materials.get("Normal_Mat")
                    if not normal_material:
                        show_message_box("Material 'Normal_Mat' not found.", "Error")
                        return
                    normal_scene.view_layers["ViewLayer"].material_override = normal_material
                    bpy.ops.render.render(scene=normal_scene.name, write_still=True)
                    bpy.data.scenes.remove(normal_scene)
                    show_message_box(f"Normal map rendered and saved to {render_path}", "Success")
                    bpy.context.scene.sna_normalpath = render_path
                # Usage example

                def main():
                    obj = bpy.context.active_object
                    if obj is None:
                        show_message_box("No active object selected.", "Error")
                        return
                    apply_normal_material(obj)
                    render_normal("normal_map.png")
                # Run the script
                main()

                def create_uv_map(obj, uv_map_name):
                    # Check if UV map already exists
                    if uv_map_name in obj.data.uv_layers:
                        uv_layer = obj.data.uv_layers[uv_map_name]
                    else:
                        # Add a new UV map
                        uv_layer = obj.data.uv_layers.new(name=uv_map_name)
                    return uv_layer.name

                def add_uv_project_modifier(obj, uv_layer_name, aspect_x, aspect_y, camera):
                    # Ensure the object is in object mode
                    if bpy.context.mode != 'OBJECT':
                        bpy.ops.object.mode_set(mode='OBJECT')
                    # Add the UV Project modifier
                    uv_project_modifier = obj.modifiers.new(name="UVProject", type='UV_PROJECT')
                    # Configure the modifier
                    uv_project_modifier.uv_layer = uv_layer_name
                    uv_project_modifier.aspect_x = aspect_x
                    uv_project_modifier.aspect_y = aspect_y
                    # Set the projector (camera)
                    uv_project_modifier.projectors[0].object = camera
                    # Apply the modifier
                    bpy.ops.object.modifier_apply(modifier=uv_project_modifier.name)
                    print(f"UV Project modifier applied on UV map '{uv_layer_name}' for object '{obj.name}' using camera '{camera.name}'.")
                # Example usage

                def main():
                    obj = bpy.context.scene.sna_activeobject
                    if obj is None:
                        print("No active object selected.")
                        return
                    if not hasattr(bpy.context.scene, "sna_bakecam"):
                        print("Bake camera not set in the scene.")
                        return
                    # Define the UV map name
                    uv_map_name = "Projected_UV"
                    # Create a new UV map
                    uv_layer_name = create_uv_map(obj, uv_map_name)
                    # Define aspect ratio (adjust if necessary)
                    aspect_x = bpy.context.scene.render.resolution_x
                    aspect_y = bpy.context.scene.render.resolution_y
                    # Get the camera object
                    camera = bpy.context.scene.sna_bakecam
                    # Add and apply the UV Project modifier
                    add_uv_project_modifier(obj, uv_layer_name, aspect_x, aspect_y, camera)
                # Run the main function
                main()
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


def sna_aigen_C4C48(layout_function, ):
    box_5363A = layout_function.box()
    box_5363A.alert = False
    box_5363A.enabled = True
    box_5363A.active = True
    box_5363A.use_property_split = False
    box_5363A.use_property_decorate = False
    box_5363A.alignment = 'Expand'.upper()
    box_5363A.scale_x = 1.0
    box_5363A.scale_y = 1.0
    if not True: box_5363A.operator_context = "EXEC_DEFAULT"
    box_25583 = box_5363A.box()
    box_25583.alert = False
    box_25583.enabled = True
    box_25583.active = True
    box_25583.use_property_split = False
    box_25583.use_property_decorate = False
    box_25583.alignment = 'Expand'.upper()
    box_25583.scale_x = 1.0
    box_25583.scale_y = 1.0
    if not True: box_25583.operator_context = "EXEC_DEFAULT"
    box_25583.prop(bpy.context.scene, 'sna_inputprompt', text='Prompt ', icon_value=0, emboss=True)
    box_25583.prop(bpy.context.scene, 'sna_outputpath', text='Output ', icon_value=0, emboss=True)
    if property_exists("bpy.context.scene.sna_outputimage.name", globals(), locals()):
        box_1DE17 = box_25583.box()
        box_1DE17.alert = False
        box_1DE17.enabled = True
        box_1DE17.active = True
        box_1DE17.use_property_split = False
        box_1DE17.use_property_decorate = False
        box_1DE17.alignment = 'Expand'.upper()
        box_1DE17.scale_x = 1.0
        box_1DE17.scale_y = 1.0
        if not True: box_1DE17.operator_context = "EXEC_DEFAULT"
        box_1DE17.template_icon(icon_value=get_id_preview_id(bpy.data.images[bpy.context.scene.sna_outputimage.name]), scale=8.360000610351562)
    layout_function = box_5363A
    sna_settings_611D4(layout_function, )


def sna_connection_37713(layout_function, ):
    box_EA894 = layout_function.box()
    box_EA894.alert = False
    box_EA894.enabled = True
    box_EA894.active = True
    box_EA894.use_property_split = False
    box_EA894.use_property_decorate = False
    box_EA894.alignment = 'Expand'.upper()
    box_EA894.scale_x = 1.0
    box_EA894.scale_y = 1.0
    if not True: box_EA894.operator_context = "EXEC_DEFAULT"
    col_207CD = box_EA894.column(heading='', align=True)
    col_207CD.alert = False
    col_207CD.enabled = True
    col_207CD.active = True
    col_207CD.use_property_split = False
    col_207CD.use_property_decorate = False
    col_207CD.scale_x = 1.0
    col_207CD.scale_y = 1.0
    col_207CD.alignment = 'Expand'.upper()
    col_207CD.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    box_AF8BC = col_207CD.box()
    box_AF8BC.alert = False
    box_AF8BC.enabled = True
    box_AF8BC.active = True
    box_AF8BC.use_property_split = False
    box_AF8BC.use_property_decorate = False
    box_AF8BC.alignment = 'Expand'.upper()
    box_AF8BC.scale_x = 1.0
    box_AF8BC.scale_y = 1.0
    if not True: box_AF8BC.operator_context = "EXEC_DEFAULT"
    row_2D02A = box_AF8BC.row(heading='', align=False)
    row_2D02A.alert = False
    row_2D02A.enabled = True
    row_2D02A.active = True
    row_2D02A.use_property_split = False
    row_2D02A.use_property_decorate = False
    row_2D02A.scale_x = 2.0
    row_2D02A.scale_y = 2.0
    row_2D02A.alignment = 'Expand'.upper()
    row_2D02A.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    row_2D02A.prop(bpy.context.scene, 'sna_controlnettype', text=' ', icon_value=0, emboss=True, expand=True)
    if bpy.context.scene.sna_controlnettype == "Local":
        col_B3BC4 = col_207CD.column(heading='', align=True)
        col_B3BC4.alert = False
        col_B3BC4.enabled = True
        col_B3BC4.active = True
        col_B3BC4.use_property_split = False
        col_B3BC4.use_property_decorate = False
        col_B3BC4.scale_x = 1.0
        col_B3BC4.scale_y = 1.0
        col_B3BC4.alignment = 'Expand'.upper()
        col_B3BC4.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
        box_0A8C0 = col_B3BC4.box()
        box_0A8C0.alert = False
        box_0A8C0.enabled = True
        box_0A8C0.active = True
        box_0A8C0.use_property_split = False
        box_0A8C0.use_property_decorate = False
        box_0A8C0.alignment = 'Center'.upper()
        box_0A8C0.scale_x = 1.0
        box_0A8C0.scale_y = 1.0
        if not True: box_0A8C0.operator_context = "EXEC_DEFAULT"
        box_58AE8 = box_0A8C0.box()
        box_58AE8.alert = False
        box_58AE8.enabled = True
        box_58AE8.active = True
        box_58AE8.use_property_split = False
        box_58AE8.use_property_decorate = False
        box_58AE8.alignment = 'Center'.upper()
        box_58AE8.scale_x = 1.0
        box_58AE8.scale_y = 1.0
        if not True: box_58AE8.operator_context = "EXEC_DEFAULT"
        box_58AE8.prop(bpy.context.scene, 'sna_urlwebui', text='WebUI URL ', icon_value=0, emboss=True)
        op = box_58AE8.operator('sna.controlnettestserver_bffa8', text='Test Server Connection', icon_value=72, emboss=True, depress=False)
        box_58AE8.label(text='Info : ' + bpy.context.scene.sna_error, icon_value=110)
        box_58AE8.prop(bpy.context.scene, 'sna_outputpath', text='', icon_value=0, emboss=True)
        layout_function = col_B3BC4
        sna_controlnet_20077(layout_function, )
    else:
        pass


class SNA_OT_Cloudrender_C0123(bpy.types.Operator):
    bl_idname = "sna.cloudrender_c0123"
    bl_label = "cloudrender"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        if bpy.context.scene.sna_randomizeseed:
            bpy.context.scene.sna_seed = random_integer(0.0, 11111.0, None)
        import importlib
        import json
        # Define module and class names
        module_name = "gradio_client"  # Specify the module name as a string
        class_name = "Client"          # Specify the class name to import
        class_name2 = "handle_file"
        # Dynamically import the module
        module = importlib.import_module(module_name)
        # Access the classes from the module
        Client = getattr(module, class_name)
        handle_file = getattr(module, class_name2)
        # Initialize the status properties
        bpy.context.scene.sna_currentstatus = "Initialized"
        bpy.context.scene.sna_statusfloat = 0.0
        # Global lock to prevent scripts from running simultaneously
        execution_lock = threading.Lock()

        def update_status(new_status, progress=None):
            """Queue status updates to be run in the main thread."""

            def update():
                bpy.context.scene.sna_currentstatus = new_status
                if progress is not None:
                    bpy.context.scene.sna_statusfloat = progress
                print(f"Status updated: {new_status}, Progress: {bpy.context.scene.sna_statusfloat}")
            # Use a timer to run the update in the main thread
            bpy.app.timers.register(update, first_interval=0)

        def execute_operator_in_main_thread():
            """Execute the operator 'projectmat_b0596' in the correct context."""
            for window in bpy.context.window_manager.windows:
                screen = window.screen
                for area in screen.areas:
                    if area.type == 'VIEW_3D':
                        with bpy.context.temp_override(window=window, area=area):
                            bpy.ops.sna.projectmat_b0596('INVOKE_DEFAULT')
                            return

        def execute_alternate_operator_in_main_thread():
            """Execute the operator 'cloudrender2_63f36' if image generation fails."""
            for window in bpy.context.window_manager.windows:
                screen = window.screen
                for area in screen.areas:
                    if area.type == 'VIEW_3D':
                        with bpy.context.temp_override(window=window, area=area):
                            bpy.ops.sna.cloudrender2_63f36('INVOKE_DEFAULT')
                            return

        def update_image_path_in_main_thread(output_path):
            """Update the image path in the main thread."""

            def update_image_path():
                bpy.context.scene.sna_outputpath = output_path
                print(f"Image path updated in scene: {output_path}")
            # Queue the update in the main thread
            bpy.app.timers.register(update_image_path, first_interval=0)

        def perform_prediction():
            progress = 0.1
            update_status("Starting Generation...", progress=progress)
            with execution_lock:  # Lock to prevent simultaneous execution
                try:
                    # Create the client for the new model
                    client = Client("https://hysts-controlnet-v1-1.hf.space/")
                    # Convert the path to a string if it is a Path object
                    normalpath_str = str(bpy.context.scene.sna_normalpath)
                    # Get the handle_file result, which is a dictionary
                    file_handle = handle_file(normalpath_str)
                    print(f"handle_file result: {file_handle}")
                    progress += 0.1
                    update_status("File Handle Obtained...", progress=progress)
                    # Extract the actual file path from the dictionary
                    file_path = file_handle['path']
                    print(f"File Path Extracted: {file_path}")
                    # Make the API call to the client using the correct file path
                    result = client.predict(
                        file_path,                            # Image file path
                        bpy.context.scene.sna_inputprompt,    # Prompt
                        "best quality",                       # Additional prompt
                        "",                                   # Negative prompt
                        1,                                    # Number of images
                        768,                                  # Image resolution
                        bpy.context.scene.sna_steps,          # Number of steps
                        bpy.context.scene.sna_cfg_scale,      # Guidance scale
                        bpy.context.scene.sna_seed,           # Seed
                        5,                                    # Some parameter (replace with actual if needed)
                        250,                                  # Some parameter (replace with actual if needed)
                        api_name="/canny"
                    )
                    progress += 0.2
                    update_status("Prediction in Progress...", progress=progress)
                    print(f"Result Directory: {result}")
                    # Check if the result directory exists
                    if not os.path.isdir(result):
                        raise FileNotFoundError(f"Directory not found: {result}")
                    progress += 0.1
                    update_status("Result Directory Confirmed...", progress=progress)
                    # Define the path to the captions.json file
                    captions_file = os.path.join(result, "captions.json")
                    if not os.path.exists(captions_file):
                        raise FileNotFoundError(f"captions.json not found in the result directory: {result}")
                    # Open and read the captions.json file
                    with open(captions_file, 'r') as f:
                        captions_data = json.load(f)
                    progress += 0.1
                    update_status("Captions File Read...", progress=progress)
                    # Extract the second image path from the JSON data
                    image_paths = list(captions_data.keys())
                    if len(image_paths) < 2:
                        raise ValueError("Less than two file paths found in captions.json.")
                    second_image_path = image_paths[1]  # Get the second image path
                    print(f"Second Image Path: {second_image_path}")
                    # Check if the second image file exists
                    if not os.path.exists(second_image_path):
                        raise FileNotFoundError(f"File not found: {second_image_path}")
                    print(f"Second image exists: {second_image_path}")
                    progress += 0.1
                    update_status("Second Image Confirmed...", progress=progress)
                    # Define the output path for the second image
                    blend_file_path = bpy.data.filepath                # Path of the .blend file
                    base_dir = os.path.dirname(blend_file_path)        # Directory containing the .blend file
                    output_dir = os.path.join(base_dir, 'generated_images')  # Subdirectory for generated images
                    os.makedirs(output_dir, exist_ok=True)             # Ensure the directory exists
                    output_path = os.path.join(output_dir, "generated_image.png")  # Full path to save the image
                    try:
                        # Manually read the second image file and write it to the new location
                        with open(second_image_path, 'rb') as f_src:
                            img_data = f_src.read()
                        # Write the data to the new path
                        with open(output_path, 'wb') as f_dst:
                            f_dst.write(img_data)
                        print(f"Image saved to {output_path}")
                        # Store only the second generated image path in Blender's scene context
                        bpy.app.timers.register(lambda: update_image_path_in_main_thread(output_path), first_interval=0)
                        # Execute the operator in the correct context
                        bpy.app.timers.register(execute_operator_in_main_thread, first_interval=0.1)
                        # Progress complete
                        progress = 1.0
                        update_status("Operation Complete!", progress=progress)
                    except FileNotFoundError as fnf_error:
                        print(f"File not found: {fnf_error}")
                        update_status(f"File not found: {fnf_error}", progress=progress)
                        # Schedule the alternate operator to run in the main thread
                        bpy.app.timers.register(execute_alternate_operator_in_main_thread, first_interval=0.1)
                    except Exception as copy_error:
                        print(f"Error copying file: {copy_error}")
                        update_status(f"Error copying result file: {copy_error}", progress=progress)
                        # Schedule the alternate operator to run in the main thread
                        bpy.app.timers.register(execute_alternate_operator_in_main_thread, first_interval=0.1)
                except Exception as e:
                    update_status(f"Error during prediction: {e}", progress=progress)
                    print(f"Error: {e}")
                    # Schedule the alternate operator to run in the main thread
                    bpy.app.timers.register(execute_alternate_operator_in_main_thread, first_interval=0.1)

        def start_prediction_thread():
            update_status("Starting prediction thread...", progress=0.0)
            # Start the prediction in a separate thread
            prediction_thread = threading.Thread(target=perform_prediction)
            prediction_thread.start()
            update_status("Prediction thread started", progress=0.05)
        # Start the process
        update_status("Script initialized", progress=0.0)
        start_prediction_thread()
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Upscaleimage_C0257(bpy.types.Operator):
    bl_idname = "sna.upscaleimage_c0257"
    bl_label = "upscaleimage"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        if bpy.context.scene.sna_upscaletype == "FineGrain":
            import os
            import shutil
            # Define module and class names
            module_name = "gradio_client"  # Specify the module name as a string
            class_name = "Client"  # Specify the class name to import
            class_name2 = "handle_file"
            # Dynamically import the module
            module = importlib.import_module(module_name)
            # Access the class from the module
            Client = getattr(module, class_name)
            handle_file = getattr(module, class_name2)
            # Initialize the status properties
            bpy.context.scene.sna_currentstatus = "Initialized"
            bpy.context.scene.sna_statusfloat = 0.0
            # Global lock to prevent scripts from running simultaneously
            execution_lock = threading.Lock()

            def update_status(new_status, progress=None):
                """Queue status updates to be run in the main thread."""

                def update():
                    bpy.context.scene.sna_currentstatus = new_status
                    if progress is not None:
                        bpy.context.scene.sna_statusfloat = progress
                    print(f"Status updated: {new_status}, Progress: {bpy.context.scene.sna_statusfloat}")
                # Use a timer to run the update in the main thread
                bpy.app.timers.register(update, first_interval=0.1)

            def execute_operator_in_main_thread():
                """Execute the operator in the correct context."""
                for window in bpy.context.window_manager.windows:
                    screen = window.screen
                    for area in screen.areas:
                        if area.type == 'VIEW_3D':  # Ensure you are in the right context, like VIEW_3D
                            with bpy.context.temp_override(window=window, area=area):
                                bpy.ops.sna.projectmat_b0596('INVOKE_DEFAULT')
                                return

            def perform_prediction():
                update_status("Starting Generation...", progress=0.1)
                with execution_lock:  # Lock to prevent simultaneous execution
                    try:
                        # Create the client for the new model           
                        client = Client("finegrain/finegrain-image-enhancer")
                        # Convert the path to a string if it is a Path object
                        normalpath_str = str(bpy.context.scene.sna_outputpath)
                        # Debug: Log the file path and prompt
                        print(f"File Path: {normalpath_str}")
                        print(f"Prompt: {bpy.context.scene.sna_inputprompt}")
                        # Make the API call to the client
                        result = client.predict(
                        input_image=handle_file(normalpath_str),
                        prompt=bpy.context.scene.sna_inputprompt,
                        negative_prompt="",
                        seed=42,
                        upscale_factor=2,
                        controlnet_scale=0.6,
                        controlnet_decay=1,
                        condition_scale=6,
                        tile_width=112,
                        tile_height=144,
                        denoise_strength=0.35,
                        num_inference_steps=18,
                        solver="DDIM",
                        api_name="/process"
                        )
                        print(result)
                        # Debug: Check if we get a result back
                        print(f"Result: {result}")
                        # Check if the result is valid before proceeding
                        if result:
                            update_status("Image generated successfully", progress=1.0)
                            # Get the image file path from the result (assuming it's in result[1])
                            generated_image_path = result[1]
                            # Define the output path for the generated image
                            blend_file_path = bpy.data.filepath  # Path of the .blend file
                            base_dir = os.path.dirname(blend_file_path)  # Directory containing the .blend file
                            output_dir = os.path.join(base_dir, 'generated_images')  # Subdirectory for generated images
                            os.makedirs(output_dir, exist_ok=True)  # Ensure the directory exists
                            # Create the full path for the renamed image
                            output_image_path = os.path.join(output_dir, "generated_image.png")
                            # Manually copy the generated image to the new location and rename it
                            try:
                                shutil.copy(generated_image_path, output_image_path)
                                print(f"Image copied and renamed to: {output_image_path}")
                                # Assign the output path to a custom property
                                bpy.context.scene.sna_outputpath = output_image_path
                                # After successful image generation, run the operator in the main thread
                                bpy.app.timers.register(execute_operator_in_main_thread, first_interval=0.1)
                            except Exception as copy_error:
                                print(f"Error copying file: {copy_error}")
                                update_status(f"Error copying file: {copy_error}", progress=0.0)
                        else:
                            update_status("No result returned from API", progress=0.0)
                            print("Error: No result returned from the API")
                    except Exception as e:
                        update_status(f"Error during prediction: {e}", progress=0.0)
                        print(f"Error: {e}")

            def start_prediction_thread():
                update_status("Starting prediction thread...", progress=0.0)
                # Start the prediction in a separate thread
                prediction_thread = threading.Thread(target=perform_prediction)
                prediction_thread.start()
                update_status("Prediction thread started", progress=0.05)
            # Start the process
            update_status("Script initialized", progress=0.0)
            start_prediction_thread()  # Run the prediction in a separate thread to prevent UI freezing
        elif bpy.context.scene.sna_upscaletype == "Clarity":
            import os
            import shutil
            # Define module and class names
            module_name = "gradio_client"  # Specify the module name as a string
            class_name = "Client"  # Specify the class name to import
            class_name2 = "handle_file"
            # Dynamically import the module
            module = importlib.import_module(module_name)
            # Access the class from the module
            Client = getattr(module, class_name)
            handle_file = getattr(module, class_name2)
            # Initialize the status properties
            bpy.context.scene.sna_currentstatus = "Initialized"
            bpy.context.scene.sna_statusfloat = 0.0
            # Global lock to prevent scripts from running simultaneously
            execution_lock = threading.Lock()

            def update_status(new_status, progress=None):
                """Queue status updates to be run in the main thread."""

                def update():
                    bpy.context.scene.sna_currentstatus = new_status
                    if progress is not None:
                        bpy.context.scene.sna_statusfloat = progress
                    print(f"Status updated: {new_status}, Progress: {bpy.context.scene.sna_statusfloat}")
                # Use a timer to run the update in the main thread
                bpy.app.timers.register(update, first_interval=0.1)

            def execute_operator_in_main_thread():
                """Execute the operator in the correct context."""
                for window in bpy.context.window_manager.windows:
                    screen = window.screen
                    for area in screen.areas:
                        if area.type == 'VIEW_3D':  # Ensure you are in the right context, like VIEW_3D
                            with bpy.context.temp_override(window=window, area=area):
                                bpy.ops.sna.projectmat_b0596('INVOKE_DEFAULT')
                                return

            def perform_prediction():
                update_status("Starting Generation...", progress=0.1)
                with execution_lock:  # Lock to prevent simultaneous execution
                    try:
                        # Create the client for the new model           
                        client = Client("jbilcke-hf/clarity-upscaler")
                        # Convert the path to a string if it is a Path object
                        normalpath_str = str(bpy.context.scene.sna_outputpath)
                        # Debug: Log the file path and prompt
                        result = client.predict(
                        handle_file(normalpath_str),
                        bpy.context.scene.sna_inputprompt,
                        "",	# str  in 'Negative Prompt' Textbox component
                        2,	# float  in 'Scale Factor' Number component
                        8,	# float (numeric value between 1 and 50) in 'Dynamic' Slider component
                        .5,	# float  in 'Creativity' Number component
                        1.6,	# float  in 'Resemblance' Number component
                        "256",	# Literal['16', '32', '48', '64', '80', '96', '112', '128', '144', '160', '176', '192', '208', '224', '240', '256']  in 'tiling_width' Dropdown component
                        "256",	# Literal['16', '32', '48', '64', '80', '96', '112', '128', '144', '160', '176', '192', '208', '224', '240', '256']  in 'tiling_height' Dropdown component
                        "juggernaut_reborn.safetensors [338b85bc4f]",	# Literal['epicrealism_naturalSinRC1VAE.safetensors [84d76a0328]', 'juggernaut_reborn.safetensors [338b85bc4f]', 'flat2DAnimerge_v45Sharp.safetensors']  in 'sd_model' Dropdown component
                        "DPM++ 2M Karras",	# Literal['DPM++ 2M Karras', 'DPM++ SDE Karras', 'DPM++ 2M SDE Exponential', 'DPM++ 2M SDE Karras', 'Euler a', 'Euler', 'LMS', 'Heun', 'DPM2', 'DPM2 a', 'DPM++ 2S a', 'DPM++ 2M', 'DPM++ SDE', 'DPM++ 2M SDE', 'DPM++ 2M SDE Heun', 'DPM++ 2M SDE Heun Karras', 'DPM++ 2M SDE Heun Exponential', 'DPM++ 3M SDE', 'DPM++ 3M SDE Karras', 'DPM++ 3M SDE Exponential', 'DPM fast', 'DPM adaptive', 'LMS Karras', 'DPM2 Karras', 'DPM2 a Karras', 'DPM++ 2S a Karras', 'Restart', 'DDIM', 'PLMS', 'UniPC']  in 'scheduler' Dropdown component
                        11,	# float (numeric value between 1 and 100) in 'Num Inference Steps' Slider component
                        3,	# float  in 'Seed' Number component
                        False,	# bool  in 'Downscaling' Checkbox component
                        768,	# float  in 'Downscaling Resolution' Number component
                        "",	# str  in 'Lora Links' Textbox component
                        "",	# str  in 'Custom Sd Model' Textbox component
                        api_name="/predict"
                        )
                        print(result)
                        # Debug: Check if we get a result back
                        print(f"Result: {result}")
                        # Check if the result is valid before proceeding
                        if result:
                            update_status("Image generated successfully", progress=1.0)
                            # Get the image file path from the result (assuming it's in result[1])
                            generated_image_path = result
                            # Define the output path for the generated image
                            blend_file_path = bpy.data.filepath  # Path of the .blend file
                            base_dir = os.path.dirname(blend_file_path)  # Directory containing the .blend file
                            output_dir = os.path.join(base_dir, 'generated_images')  # Subdirectory for generated images
                            os.makedirs(output_dir, exist_ok=True)  # Ensure the directory exists
                            # Create the full path for the renamed image
                            output_image_path = os.path.join(output_dir, "generated_image.png")
                            # Manually copy the generated image to the new location and rename it
                            try:
                                shutil.copy(generated_image_path, output_image_path)
                                print(f"Image copied and renamed to: {output_image_path}")
                                # Assign the output path to a custom property
                                bpy.context.scene.sna_outputpath = output_image_path
                                # After successful image generation, run the operator in the main thread
                                bpy.app.timers.register(execute_operator_in_main_thread, first_interval=0.1)
                            except Exception as copy_error:
                                print(f"Error copying file: {copy_error}")
                                update_status(f"Error copying file: {copy_error}", progress=0.0)
                        else:
                            update_status("No result returned from API", progress=0.0)
                            print("Error: No result returned from the API")
                    except Exception as e:
                        update_status(f"Error during prediction: {e}", progress=0.0)
                        print(f"Error: {e}")

            def start_prediction_thread():
                update_status("Starting prediction thread...", progress=0.0)
                # Start the prediction in a separate thread
                prediction_thread = threading.Thread(target=perform_prediction)
                prediction_thread.start()
                update_status("Prediction thread started", progress=0.05)
            # Start the process
            update_status("Script initialized", progress=0.0)
            start_prediction_thread()  # Run the prediction in a separate thread to prevent UI freezing
        else:
            pass
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Cloudrender2_63F36(bpy.types.Operator):
    bl_idname = "sna.cloudrender2_63f36"
    bl_label = "cloudrender2"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        if bpy.context.scene.sna_randomizeseed:
            bpy.context.scene.sna_seed = random_integer(0.0, 11111.0, None)
        import importlib
        # Define module and class names
        module_name = "gradio_client"  # Specify the module name as a string
        class_name = "Client"  # Specify the class name to import
        class_name2 = "handle_file"
        # Dynamically import the module
        module = importlib.import_module(module_name)
        # Access the class from the module
        Client = getattr(module, class_name)
        handle_file = getattr(module, class_name2)
        # Initialize the status properties
        bpy.context.scene.sna_currentstatus = "Initialized"
        bpy.context.scene.sna_statusfloat = 0.0
        # Global lock to prevent scripts from running simultaneously
        execution_lock = threading.Lock()

        def update_status(new_status, progress=None):
            """Queue status updates to be run in the main thread."""

            def update():
                bpy.context.scene.sna_currentstatus = new_status
                if progress is not None:
                    bpy.context.scene.sna_statusfloat = progress
                print(f"Status updated: {new_status}, Progress: {bpy.context.scene.sna_statusfloat}")
            # Use a timer to run the update in the main thread
            bpy.app.timers.register(update, first_interval=0)

        def execute_operator_in_main_thread():
            """Execute the operator in the correct context."""
            for window in bpy.context.window_manager.windows:
                screen = window.screen
                for area in screen.areas:
                    if area.type == 'VIEW_3D':  # Ensure you are in the right context, like VIEW_3D
                        with bpy.context.temp_override(window=window, area=area):
                            bpy.ops.sna.projectmat_b0596('INVOKE_DEFAULT')
                            return

        def update_image_path_in_main_thread(output_path):
            """Update the image path in the main thread."""

            def update_image_path():
                bpy.context.scene.sna_outputpath = output_path
                print(f"Image path updated in scene: {output_path}")
            # Queue the update in the main thread
            bpy.app.timers.register(update_image_path, first_interval=0)

        def perform_prediction():
            progress = 0.1
            update_status("Starting Generation...", progress=progress)
            with execution_lock:  # Lock to prevent simultaneous execution
                try:
                    client = Client("terrapretapermaculture/ControlNet-v1-1-B")
                    # Convert the path to a string if it is a Path object
                    normalpath_str = str(bpy.context.scene.sna_depthpath)
                    # Get the handle_file result, which is a dictionary
                    file_handle = handle_file(normalpath_str)
                    print(f"handle_file result: {file_handle}")  # Print the result to inspect
                    progress += 0.1
                    update_status("File Handle Obtained...", progress=progress)
                    # Extract the actual file path from the dictionary
                    file_path = file_handle['path']
                    print(f"File Path Extracted: {file_path}")
                    # Call the API to perform the prediction
                    result = client.predict(
                        image=handle_file(bpy.context.scene.sna_depthpath),
                        prompt=bpy.context.scene.sna_inputprompt,
                        additional_prompt="best quality",
                        negative_prompt="",
                        num_images=1,
                        image_resolution=768,
                        preprocess_resolution=384,
                        num_steps=bpy.context.scene.sna_steps,
                        guidance_scale=bpy.context.scene.sna_cfg_scale,
                        seed=bpy.context.scene.sna_seed,
                        preprocessor_name="None",
                        api_name="/predict"
                    )
                    progress += 0.2
                    update_status("Prediction in Progress...", progress=progress)
                    print(f"Prediction Result: {result}")
                    # Extract the second image file path from the result list
                    if isinstance(result, list) and len(result) >= 2:
                        second_result = result[1]  # Get the second image from the list
                        image_path = second_result.get("image", "")
                        if not image_path:
                            raise ValueError("No image path found in the second result.")
                        # Define the output path for the second image
                        blend_file_path = bpy.data.filepath  # Path of the .blend file
                        base_dir = os.path.dirname(blend_file_path)  # Directory containing the .blend file
                        output_dir = os.path.join(base_dir, 'generated_images')  # Subdirectory for generated images
                        os.makedirs(output_dir, exist_ok=True)  # Ensure the directory exists
                        output_path = os.path.join(output_dir, "generated_image.png")  # Full path to save the image
                        try:
                            # Manually read the second image file and write it to the new location
                            with open(image_path, 'rb') as f_src:
                                img_data = f_src.read()
                            # Write the data to the new path
                            with open(output_path, 'wb') as f_dst:
                                f_dst.write(img_data)
                            print(f"Second image saved to {output_path}")
                            # Store only the second generated image path in Blender's scene context
                            bpy.app.timers.register(lambda: update_image_path_in_main_thread(output_path), first_interval=0)
                            # Execute the operator in the correct context
                            bpy.app.timers.register(execute_operator_in_main_thread, first_interval=0.1)
                            # Progress complete
                            progress = 1.0
                            update_status("Operation Complete!", progress=progress)
                        except FileNotFoundError as fnf_error:
                            print(f"File not found: {fnf_error}")
                            update_status(f"File not found: {fnf_error}", progress=progress)
                        except Exception as copy_error:
                            print(f"Error copying file: {copy_error}")
                            update_status(f"Error copying result file: {copy_error}", progress=progress)
                    else:
                        raise ValueError("Unexpected result format or less than two images returned from the prediction.")
                except Exception as e:
                    update_status(f"Error during prediction: {e}", progress=progress)
                    print(f"Error: {e}")

        def start_prediction_thread():
            update_status("Starting prediction thread...", progress=0.0)
            # Start the prediction in a separate thread
            prediction_thread = threading.Thread(target=perform_prediction)
            prediction_thread.start()
            update_status("Prediction thread started", progress=0.05)
        # Start the process
        update_status("Script initialized", progress=0.0)
        start_prediction_thread()
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


def sna_controlnetnormal_enum_items(self, context):
    enum_items = controlnet['sna_controlnet_normal_models_list_enum']
    return [make_enum_item(item[0], item[1], item[2], item[3], i) for i, item in enumerate(enum_items)]


def sna_availablemodels_enum_items(self, context):
    enum_items = controlnet['sna_stable_models_list_enum']
    return [make_enum_item(item[0], item[1], item[2], item[3], i) for i, item in enumerate(enum_items)]


class SNA_OT_Checkmodels_2E559(bpy.types.Operator):
    bl_idname = "sna.checkmodels_2e559"
    bl_label = "checkmodels"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        controlnet['sna_controlnet_models_list'] = []
        controlnet['sna_controlnet_normal_models_list_enum'] = []
        module_name3 = "requests"
        module3 = importlib.import_module(module_name3)
        requests = module3
        # Global variable to store ControlNet models

        def fetch_controlnet_models():
            # Define the URL for the ControlNet models endpoint
            url = bpy.context.scene.sna_urlwebui + "/controlnet/model_list"
            try:
                # Make a GET request to fetch the list of models
                response = requests.get(url)
                if response.status_code == 200:
                    models = response.json().get("model_list", [])
                    if models:
                        print("ControlNet models available:")
                        controlnet['sna_controlnet_models_list'] = models 
                        for model in models:
                            print(f"- {model}")
                           # controlnet['sna_controlnet_models_list'].append(model)
                        return models
                    else:
                        print("ControlNet is installed, but no models are available.")
                        return [("NONE", "No Models Available", "")]
                else:
                    print(f"Failed to retrieve ControlNet models. Status code: {response.status_code}")
                    return [("NONE", "No Models Available", "")]
            except requests.exceptions.RequestException as e:
                print(f"Failed to connect to the server: {e}")
                return [("NONE", "No Models Available", "")]
        # Fetch models initially when the script runs
        fetch_controlnet_models()
        print(str(controlnet['sna_controlnet_models_list']))
        if (0 != len(controlnet['sna_controlnet_models_list'])):
            for i_16C45 in range(len(controlnet['sna_controlnet_models_list'])):
                if 'normal' in controlnet['sna_controlnet_models_list'][i_16C45]:
                    print(controlnet['sna_controlnet_models_list'][i_16C45])
                    controlnet['sna_controlnet_normal_models_list_enum'].append([controlnet['sna_controlnet_models_list'][i_16C45], controlnet['sna_controlnet_models_list'][i_16C45], '', 0])
                if 'depth' in controlnet['sna_controlnet_models_list'][i_16C45]:
                    controlnet['sna_controlnet_depth_models_list_enum'].append([controlnet['sna_controlnet_models_list'][i_16C45], controlnet['sna_controlnet_models_list'][i_16C45], '', 0])
        else:
            controlnet['sna_controlnet_normal_models_list_enum'].append(['No Model Found', 'No Model Found', '', 0])
        controlnet['sna_stable_models_list'] = []
        controlnet['sna_stable_models_list_enum'] = []
        model_titles = None
        module_name3 = "requests"
        module3 = importlib.import_module(module_name3)
        requests = module3

        def check_available_sd_models():
            url = bpy.context.scene.sna_urlwebui + "/sdapi/v1/sd-models"  # Endpoint to get available models
            try:
                response = requests.get(url)
                # Check if the request was successful
                if response.status_code == 200:
                    models = response.json()
                    # Extract and return the titles of the available models
                    model_titles = [model['title'] for model in models]
                    # Print the list of available model titles
                    print("Available Stable Diffusion Models:")
                    for title in model_titles:
                        print(f"- {title}")
                    return model_titles
                else:
                    print(f"Failed to retrieve models: {response.status_code} - {response.text}")
                    return None
            except requests.exceptions.RequestException as e:
                print(f"Failed to connect to the server: {e}")
                return None
        # Example usage
        model_titles = check_available_sd_models()
        # model_titles now contains just the titles of the available models
        if (None != model_titles):
            print(str(model_titles))
            for i_86DA5 in range(len(model_titles)):
                controlnet['sna_stable_models_list_enum'].append([model_titles[i_86DA5], model_titles[i_86DA5], model_titles[i_86DA5], 0])
        else:
            controlnet['sna_controlnet_normal_models_list_enum'].append(['No Model Found', 'No Model Found', '', 0])
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Ai_Render_4Aae9(bpy.types.Operator):
    bl_idname = "sna.ai_render_4aae9"
    bl_label = "AI Render"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        if bpy.context.scene.sna_randomizeseed:
            bpy.context.scene.sna_seed = random_integer(0.0, 11111.0, None)
        import os
        import importlib
        module_name2 = "cv2"
        module_name3 = "requests"
        module2 = importlib.import_module(module_name2)
        module3 = importlib.import_module(module_name3)
        cv2 = module2
        requests = module3
        # Global lock to prevent scripts from running simultaneously
        execution_lock = threading.Lock()

        def update_status(new_status, progress=None):
            """Queue status updates to be run in the main thread."""

            def update():
                bpy.context.scene.sna_currentstatus = new_status
                if progress is not None:
                    bpy.context.scene.sna_statusfloat = progress
                print(f"Status updated: {new_status}, Progress: {bpy.context.scene.sna_statusfloat}")
            # Use a timer to run the update in the main thread
            bpy.app.timers.register(update, first_interval=0)

        def read_image(img_path: str) -> str:
            """Reads an image file and returns it as a base64-encoded string."""
            try:
                print(f"Reading image from {img_path}")
                img = cv2.imread(img_path)
                if img is None:
                    raise ValueError(f"Failed to read image at {img_path}")
                _, img_bytes = cv2.imencode(".png", img)
                encoded_image = base64.b64encode(img_bytes).decode("utf-8")
                return encoded_image
            except Exception as e:
                print(f"Error reading image {img_path}: {e}")
                return None

        def execute_operator_in_main_thread():
            """Execute the operator in the correct context after image generation."""
            for window in bpy.context.window_manager.windows:
                screen = window.screen
                for area in screen.areas:
                    if area.type == 'VIEW_3D':  # Ensure you're in the right context, like VIEW_3D
                        with bpy.context.temp_override(window=window, area=area):
                            bpy.ops.sna.projectmat_b0596('INVOKE_DEFAULT')
                            return

        def perform_prediction():
            progress = 0.1
            update_status("Starting image generation...", progress=progress)
            # Retrieve the normal map and depth map paths from Blender's context
            normal_map_path = bpy.context.scene.sna_normalpath
            depth_map_path = bpy.context.scene.sna_depthpath
            width = bpy.context.scene.render.resolution_x * bpy.context.scene.sna_resolution_multiplier
            height = bpy.context.scene.render.resolution_y * bpy.context.scene.sna_resolution_multiplier
            # Ensure the files exist before proceeding
            if not os.path.exists(normal_map_path):
                update_status(f"Error: Normal map file not found at {normal_map_path}", progress=progress)
                return
            elif not os.path.exists(depth_map_path):
                update_status(f"Error: Depth map file not found at {depth_map_path}", progress=progress)
                return
            progress += 0.1
            update_status("Reading images...", progress=progress)
            # Read and encode the normal map image if available
            base64_normal_image = None
            if bpy.context.scene.sna_controlnetnormal:
                base64_normal_image = read_image(normal_map_path)
                if not base64_normal_image:
                    update_status(f"Failed to process normal map image: {normal_map_path}", progress=progress)
                    return
            # Read and encode the depth map image if available
            base64_depth_image = None
            if bpy.context.scene.sna_controlnetdepth:
                base64_depth_image = read_image(depth_map_path)
                if not base64_depth_image:
                    update_status(f"Failed to process depth map image: {depth_map_path}", progress=progress)
                    return
            # Prepare the ControlNet units based on model availability
            controlnet_args = []
            # If the normal model is available, create the normal map ControlNet unit
            if base64_normal_image:
                print("Preparing normal map ControlNet unit.")
                unit1 = {
                    "image": base64_normal_image,
                    "mask_image": None,
                    "control_mode": "Balanced",
                    "enabled": True,
                    "guidance_end": 1,
                    "guidance_start": 0,
                    "pixel_perfect": True,
                    "processor_res": 512,
                    "resize_mode": "Just Resize",
                    "weight": bpy.context.scene.sna_normal_weight,
                    "model": bpy.context.scene.sna_controlnetnormal,
                    "save_detected_map": True,
                    "hr_option": "Both",
                }
                controlnet_args.append(unit1)
            # If the depth model is available, create the depth map ControlNet unit
            if base64_depth_image:
                print("Preparing depth map ControlNet unit.")
                unit2 = {
                    "image": base64_depth_image,
                    "mask_image": None,
                    "control_mode": "Balanced",
                    "enabled": True,
                    "guidance_end": 1,
                    "guidance_start": 0,
                    "pixel_perfect": True,
                    "processor_res": 512,
                    "resize_mode": "Just Resize",
                    "weight": bpy.context.scene.sna_depth_weight,
                    "model": bpy.context.scene.sna_controlnetdepth,
                    "save_detected_map": True,
                    "hr_option": "Both",
                }
                controlnet_args.append(unit2)
            # Define the payload for the text-to-image generation, including ControlNet args if available
            payload = {
                "prompt": bpy.context.scene.sna_inputprompt,
                "batch_size": 1,
                "cfg_scale": bpy.context.scene.sna_cfg_scale,
                "width": width,
                "height": height,
                "steps": bpy.context.scene.sna_steps,
                "seed": bpy.context.scene.sna_seed,
                "sampler_name": "Euler a",
                "sd_model_checkpoint": bpy.context.scene.sna_availablemodels,
                "alwayson_scripts": {
                    "ControlNet": {
                        "args": controlnet_args  # Include only the available ControlNet units in the payload
                    }
                }
            }
            progress += 0.2
            update_status("Sending request to API...", progress=progress)
            # Send the request to the Stable Diffusion API
            url = bpy.context.scene.sna_urlwebui + "/sdapi/v1/txt2img"
            response = requests.post(url, json=payload)
            progress += 0.2
            # Check the response
            if response.status_code == 200:
                imgs = response.json().get("images", [])
                if imgs:
                    # Decode the first image
                    img_data = base64.b64decode(imgs[0])
                    # Define the output path
                    blend_file_path = bpy.data.filepath
                    base_dir = os.path.dirname(blend_file_path)
                    output_dir = os.path.join(base_dir, 'generated_images')
                    os.makedirs(output_dir, exist_ok=True)
                    output_path = os.path.join(output_dir, "generated_image.png")
                    # Save the generated image
                    with open(output_path, "wb") as f:
                        f.write(img_data)
                    update_status(f"Image saved to {output_path}", progress=1.0)
                    bpy.context.scene.sna_outputpath = output_path  # Store the path in Blender's context
                    bpy.app.timers.register(lambda: bpy.context.area.tag_redraw(), first_interval=0)
                    # Execute the operator in the correct context after image generation
                    bpy.app.timers.register(execute_operator_in_main_thread, first_interval=0.1)
                else:
                    update_status("No images returned by the API.", progress=progress)
            else:
                update_status(f"Failed to generate image: {response.status_code} - {response.text}", progress=progress)

        def start_prediction_thread():
            update_status("Starting prediction thread...", progress=0.0)
            # Start the prediction in a separate thread
            prediction_thread = threading.Thread(target=perform_prediction)
            prediction_thread.start()
            update_status("Prediction thread started", progress=0.05)
        # Call this function to start the process
        start_prediction_thread()
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Set_Sd_Model_2D717(bpy.types.Operator):
    bl_idname = "sna.set_sd_model_2d717"
    bl_label = "set_sd_model"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        bpy.context.scene.sna_sd_model = bpy.context.scene.sna_availablemodels
        if bpy.context and bpy.context.screen:
            for a in bpy.context.screen.areas:
                a.tag_redraw()
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


def sna_controlnetdepth_enum_items(self, context):
    enum_items = controlnet['sna_controlnet_depth_models_list_enum']
    return [make_enum_item(item[0], item[1], item[2], item[3], i) for i, item in enumerate(enum_items)]


def sna_controlnet_20077(layout_function, ):
    box_C10A2 = layout_function.box()
    box_C10A2.alert = False
    box_C10A2.enabled = True
    box_C10A2.active = True
    box_C10A2.use_property_split = False
    box_C10A2.use_property_decorate = False
    box_C10A2.alignment = 'Left'.upper()
    box_C10A2.scale_x = 1.0
    box_C10A2.scale_y = 1.0
    if not True: box_C10A2.operator_context = "EXEC_DEFAULT"
    row_E76CA = box_C10A2.row(heading='', align=False)
    row_E76CA.alert = False
    row_E76CA.enabled = True
    row_E76CA.active = True
    row_E76CA.use_property_split = False
    row_E76CA.use_property_decorate = False
    row_E76CA.scale_x = 1.0
    row_E76CA.scale_y = 1.0
    row_E76CA.alignment = 'Expand'.upper()
    row_E76CA.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    split_2E344 = row_E76CA.split(factor=0.6111111044883728, align=True)
    split_2E344.alert = False
    split_2E344.enabled = True
    split_2E344.active = True
    split_2E344.use_property_split = False
    split_2E344.use_property_decorate = False
    split_2E344.scale_x = 1.0
    split_2E344.scale_y = 1.0
    split_2E344.alignment = 'Expand'.upper()
    if not True: split_2E344.operator_context = "EXEC_DEFAULT"
    split_2E344.prop(bpy.context.scene, 'sna_error', text='', icon_value=222, emboss=False)
    op = split_2E344.operator('sna.checkmodels_2e559', text='Search Available Models', icon_value=30, emboss=True, depress=False)
    box_2391C = box_C10A2.box()
    box_2391C.alert = False
    box_2391C.enabled = True
    box_2391C.active = True
    box_2391C.use_property_split = True
    box_2391C.use_property_decorate = False
    box_2391C.alignment = 'Expand'.upper()
    box_2391C.scale_x = 1.0
    box_2391C.scale_y = 1.0
    if not True: box_2391C.operator_context = "EXEC_DEFAULT"
    col_8D9ED = box_2391C.column(heading='', align=False)
    col_8D9ED.alert = False
    col_8D9ED.enabled = True
    col_8D9ED.active = True
    col_8D9ED.use_property_split = False
    col_8D9ED.use_property_decorate = False
    col_8D9ED.scale_x = 1.0
    col_8D9ED.scale_y = 1.0
    col_8D9ED.alignment = 'Expand'.upper()
    col_8D9ED.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    col_8D9ED.label(text='Stable Diffusion Models :', icon_value=872)
    col_8D9ED.prop(bpy.context.scene, 'sna_availablemodels', text='', icon_value=18, emboss=True)
    col_5821E = box_C10A2.column(heading='', align=False)
    col_5821E.alert = False
    col_5821E.enabled = True
    col_5821E.active = True
    col_5821E.use_property_split = True
    col_5821E.use_property_decorate = False
    col_5821E.scale_x = 1.0
    col_5821E.scale_y = 1.0
    col_5821E.alignment = 'Expand'.upper()
    col_5821E.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    box_65160 = col_5821E.box()
    box_65160.alert = False
    box_65160.enabled = True
    box_65160.active = True
    box_65160.use_property_split = False
    box_65160.use_property_decorate = False
    box_65160.alignment = 'Left'.upper()
    box_65160.scale_x = 1.0
    box_65160.scale_y = 1.0
    if not True: box_65160.operator_context = "EXEC_DEFAULT"
    box_65160.label(text='ControlNet Normal Models :', icon_value=876)
    box_65160.prop(bpy.context.scene, 'sna_controlnetnormal', text='', icon_value=18, emboss=True, expand=False)
    box_94E18 = col_5821E.box()
    box_94E18.alert = False
    box_94E18.enabled = True
    box_94E18.active = True
    box_94E18.use_property_split = False
    box_94E18.use_property_decorate = False
    box_94E18.alignment = 'Left'.upper()
    box_94E18.scale_x = 1.0
    box_94E18.scale_y = 1.0
    if not True: box_94E18.operator_context = "EXEC_DEFAULT"
    box_94E18.label(text='ControlNet Depth Models :', icon_value=871)
    box_94E18.prop(bpy.context.scene, 'sna_controlnetdepth', text='', icon_value=18, emboss=True, expand=False)


class SNA_OT_Controlnettestserver_Bffa8(bpy.types.Operator):
    bl_idname = "sna.controlnettestserver_bffa8"
    bl_label = "controlnettestserver"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        import importlib
        module_name3 = "requests"
        module3 = importlib.import_module(module_name3)
        requests = module3

        def test_server_connection():
            url = bpy.context.scene.sna_urlwebui   # Endpoint to test
            try:
                response = requests.get(url)
                # Check if the server responded with a success status code
                if response.status_code == 200:
                    print("Server connection successful!")
                    bpy.context.scene.sna_error = "Server connection successful!"
                    return True
                else:
                    print(f"Server responded with status code {response.status_code}")
                    return False
            except requests.exceptions.RequestException as e:
                print(f"Failed to connect to the server: {e}")
                bpy.context.scene.sna_error = "Failed to connect to the server: {e}"
                return False
        # Example usage of the test
        if test_server_connection():
            # Proceed with generating the image
            bpy.context.scene.sna_error = "Server connection successful!"
        else:
            print("Server connection failed. Image generation aborted.")
            bpy.context.scene.sna_error = "Server connection failed. Image generation aborted."
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


def sna_settings_611D4(layout_function, ):
    box_E56A8 = layout_function.box()
    box_E56A8.alert = False
    box_E56A8.enabled = True
    box_E56A8.active = True
    box_E56A8.use_property_split = False
    box_E56A8.use_property_decorate = False
    box_E56A8.alignment = 'Expand'.upper()
    box_E56A8.scale_x = 1.0
    box_E56A8.scale_y = 1.0
    if not True: box_E56A8.operator_context = "EXEC_DEFAULT"
    col_6C2AD = box_E56A8.column(heading='', align=True)
    col_6C2AD.alert = False
    col_6C2AD.enabled = True
    col_6C2AD.active = True
    col_6C2AD.use_property_split = True
    col_6C2AD.use_property_decorate = False
    col_6C2AD.scale_x = 1.0
    col_6C2AD.scale_y = 1.0
    col_6C2AD.alignment = 'Center'.upper()
    col_6C2AD.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    box_37057 = col_6C2AD.box()
    box_37057.alert = False
    box_37057.enabled = True
    box_37057.active = True
    box_37057.use_property_split = False
    box_37057.use_property_decorate = False
    box_37057.alignment = 'Expand'.upper()
    box_37057.scale_x = 1.0
    box_37057.scale_y = 1.0
    if not True: box_37057.operator_context = "EXEC_DEFAULT"
    split_7CAF7 = box_37057.split(factor=0.49444445967674255, align=True)
    split_7CAF7.alert = False
    split_7CAF7.enabled = True
    split_7CAF7.active = True
    split_7CAF7.use_property_split = False
    split_7CAF7.use_property_decorate = False
    split_7CAF7.scale_x = 1.0
    split_7CAF7.scale_y = 1.0
    split_7CAF7.alignment = 'Expand'.upper()
    if not True: split_7CAF7.operator_context = "EXEC_DEFAULT"
    split_7CAF7.label(text='AI Settings :', icon_value=23)
    box_77001 = col_6C2AD.box()
    box_77001.alert = False
    box_77001.enabled = True
    box_77001.active = True
    box_77001.use_property_split = True
    box_77001.use_property_decorate = False
    box_77001.alignment = 'Expand'.upper()
    box_77001.scale_x = 1.0
    box_77001.scale_y = 1.0
    if not True: box_77001.operator_context = "EXEC_DEFAULT"
    col_77E17 = box_77001.column(heading='', align=True)
    col_77E17.alert = False
    col_77E17.enabled = True
    col_77E17.active = True
    col_77E17.use_property_split = True
    col_77E17.use_property_decorate = False
    col_77E17.scale_x = 1.0
    col_77E17.scale_y = 1.0
    col_77E17.alignment = 'Center'.upper()
    col_77E17.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    if (bpy.context.scene.sna_controlnettype == 'Cloud'):
        pass
    else:
        col_77E17.prop(bpy.context.scene, 'sna_resolution_multiplier', text='AI Resolution Scale :', icon_value=27, emboss=True, expand=True)
    if (bpy.context.scene.sna_controlnettype == 'Cloud'):
        pass
    else:
        col_77E17.prop(bpy.context.scene, 'sna_normal_weight', text='Normal Weight :', icon_value=27, emboss=True, expand=True)
    if (bpy.context.scene.sna_controlnettype == 'Cloud'):
        pass
    else:
        col_77E17.prop(bpy.context.scene, 'sna_depth_weight', text='Depth Weight :', icon_value=27, emboss=True, expand=True)
    col_77E17.prop(bpy.context.scene, 'sna_steps', text='Steps :', icon_value=27, emboss=True, expand=True)
    col_77E17.prop(bpy.context.scene, 'sna_cfg_scale', text='Cfg Scale :', icon_value=0, emboss=True, expand=True)
    col_77E17.prop(bpy.context.scene, 'sna_seed', text='Seed :', icon_value=0, emboss=True, expand=True)
    col_77E17.prop(bpy.context.scene, 'sna_randomizeseed', text='Randomize Seed', icon_value=0, emboss=True)
    if property_exists("bpy.context.scene.sna_activeobject.modifiers['combine']['Socket_5']", globals(), locals()):
        col_0D07A = col_6C2AD.column(heading='', align=True)
        col_0D07A.alert = False
        col_0D07A.enabled = True
        col_0D07A.active = True
        col_0D07A.use_property_split = True
        col_0D07A.use_property_decorate = False
        col_0D07A.scale_x = 1.0
        col_0D07A.scale_y = 1.0
        col_0D07A.alignment = 'Center'.upper()
        col_0D07A.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
        box_3B425 = col_0D07A.box()
        box_3B425.alert = False
        box_3B425.enabled = True
        box_3B425.active = True
        box_3B425.use_property_split = False
        box_3B425.use_property_decorate = False
        box_3B425.alignment = 'Expand'.upper()
        box_3B425.scale_x = 1.0
        box_3B425.scale_y = 1.0
        if not True: box_3B425.operator_context = "EXEC_DEFAULT"
        box_3B425.label(text='Projection Settings :', icon_value=23)
        box_2A668 = col_0D07A.box()
        box_2A668.alert = False
        box_2A668.enabled = True
        box_2A668.active = True
        box_2A668.use_property_split = False
        box_2A668.use_property_decorate = False
        box_2A668.alignment = 'Expand'.upper()
        box_2A668.scale_x = 1.0
        box_2A668.scale_y = 1.0
        if not True: box_2A668.operator_context = "EXEC_DEFAULT"
        col_02C3D = box_2A668.column(heading='', align=True)
        col_02C3D.alert = False
        col_02C3D.enabled = True
        col_02C3D.active = True
        col_02C3D.use_property_split = True
        col_02C3D.use_property_decorate = False
        col_02C3D.scale_x = 1.0
        col_02C3D.scale_y = 1.0
        col_02C3D.alignment = 'Expand'.upper()
        col_02C3D.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
        if property_exists("bpy.context.scene.sna_activeobject.modifiers['combine']['Socket_2']", globals(), locals()):
            attr_68E3F = '["' + str('Socket_2' + '"]') 
            col_02C3D.prop(bpy.context.scene.sna_activeobject.modifiers['combine'], attr_68E3F, text='Smooth :', icon_value=0, emboss=True, expand=True)
        if property_exists("bpy.context.scene.sna_activeobject.modifiers['combine']['Socket_5']", globals(), locals()):
            attr_A773E = '["' + str('Socket_5' + '"]') 
            col_02C3D.prop(bpy.context.scene.sna_activeobject.modifiers['combine'], attr_A773E, text='Direction Weight :', icon_value=0, emboss=True, expand=True)


def sna_generate_B95E5(layout_function, ):
    box_90E51 = layout_function.box()
    box_90E51.alert = False
    box_90E51.enabled = True
    box_90E51.active = True
    box_90E51.use_property_split = False
    box_90E51.use_property_decorate = False
    box_90E51.alignment = 'Expand'.upper()
    box_90E51.scale_x = 2.0
    box_90E51.scale_y = 2.0
    if not True: box_90E51.operator_context = "EXEC_DEFAULT"
    row_2D8C7 = box_90E51.row(heading='', align=False)
    row_2D8C7.alert = False
    row_2D8C7.enabled = True
    row_2D8C7.active = True
    row_2D8C7.use_property_split = False
    row_2D8C7.use_property_decorate = False
    row_2D8C7.scale_x = 1.0
    row_2D8C7.scale_y = 1.0
    row_2D8C7.alignment = 'Expand'.upper()
    row_2D8C7.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    if bpy.context.scene.sna_controlnettype == "Local":
        box_FA0ED = row_2D8C7.box()
        box_FA0ED.alert = False
        box_FA0ED.enabled = True
        box_FA0ED.active = True
        box_FA0ED.use_property_split = False
        box_FA0ED.use_property_decorate = False
        box_FA0ED.alignment = 'Expand'.upper()
        box_FA0ED.scale_x = 1.0
        box_FA0ED.scale_y = 1.0
        if not True: box_FA0ED.operator_context = "EXEC_DEFAULT"
        op = box_FA0ED.operator('sna.ai_render_4aae9', text='Generate Guided AI Image', icon_value=158, emboss=True, depress=False)
    elif bpy.context.scene.sna_controlnettype == "Cloud":
        box_0AB3F = row_2D8C7.box()
        box_0AB3F.alert = False
        box_0AB3F.enabled = True
        box_0AB3F.active = True
        box_0AB3F.use_property_split = False
        box_0AB3F.use_property_decorate = False
        box_0AB3F.alignment = 'Expand'.upper()
        box_0AB3F.scale_x = 1.0
        box_0AB3F.scale_y = 1.0
        if not True: box_0AB3F.operator_context = "EXEC_DEFAULT"
        op = box_0AB3F.operator('sna.cloudrender_c0123', text='Generate Guided AI Image', icon_value=158, emboss=True, depress=False)
    else:
        pass


class SNA_OT_Resetstatus_0D6C7(bpy.types.Operator):
    bl_idname = "sna.resetstatus_0d6c7"
    bl_label = "resetstatus"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        bpy.context.scene.sna_statusfloat = 0.0
        bpy.context.scene.sna_currentstatus = 'Progress Info Cleared!'
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_AddonPreferences_FE2DA(bpy.types.AddonPreferences):
    bl_idname = 'autopainter_ai'

    def draw(self, context):
        if not (False):
            layout = self.layout 
            layout_function = layout
            sna_dependency_A098E(layout_function, )


class SNA_OT_Check_Dependencies_70B8B(bpy.types.Operator):
    bl_idname = "sna.check_dependencies_70b8b"
    bl_label = "check_dependencies"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        import bpy

        def check_module_installed(module_name):
            """
            Check if a module is installed in the current Blender Python environment.
            Returns True if installed, False otherwise.
            """
            try:
                importlib.import_module(module_name)
                return True, f"'{module_name}' is installed."
            except ImportError:
                return False, f"'{module_name}' is NOT installed."
        # List of modules to check
        modules_to_check = [
            'gradio_client',  # For Gradio client
            'requests',       # For HTTP requests
            'cv2'             # OpenCV (cv2)
        ]
        # Check the installation status of each module and store results in a string
        dependency_info = []
        all_installed = True
        for module in modules_to_check:
            installed, status_message = check_module_installed(module)
            print(status_message)  # Print the status to the console
            # If any module is not installed, add the message and set all_installed to False
            if not installed:
                dependency_info.append(status_message)
                all_installed = False
        # Check if all modules are installed and set the message accordingly
        if all_installed:
            final_message = "All required modules are installed."
            bpy.context.scene['sna_dependency_info'] = final_message
        else:
            # Append the final message for missing modules
            dependency_info.append("Some modules are missing. Please install the missing dependencies.")
            bpy.context.scene['sna_dependency_info'] = "\n".join(dependency_info)
        # Output the result to the console
        print("\nDependency information stored in 'sna_dependency_info':")
        print(bpy.context.scene['sna_dependency_info'])
        self.report({'WARNING'}, message=bpy.context.scene.sna_dependency_info)
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Install_Dependencies_3D3B5(bpy.types.Operator):# 环境安装
    bl_idname = "sna.install_dependencies_3d3b5"
    bl_label = "install_dependencies"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        import sys
        from pathlib import Path
        import importlib.util

        def check_admin_privileges():
            """
            Check if Blender is running with administrator privileges (Windows only).
            """
            try:
                # For Windows: Check if the process has administrator privileges
                result = subprocess.run(["net", "session"], capture_output=True, text=True)
                if result.returncode == 0:
                    return True
                else:
                    return False
            except Exception as e:
                print(f"Error checking admin privileges: {e}")
                return False

        def install_dependencies():
            """
            Main function to check admin privileges, install required packages, and update Blender's scene info.
            """
            # Check admin privileges and store the result
            is_admin = check_admin_privileges()
            admin_status_message = "Blender is running with administrator privileges." if is_admin else "Blender is NOT running with administrator privileges."
            # Store admin status in Blender's scene property and print it
            bpy.context.scene['sna_dependency_info'] = admin_status_message
            print(admin_status_message)
            # If not running as admin, stop further actions and store the info
            if not is_admin:
                print("Aborting script since Blender is not running with administrator privileges.")
                bpy.context.scene['sna_dependency_info'] += "\nInstallation aborted: Blender is not running with administrator privileges."
                return  # Safely exit the function

            def install_package(package):
                """
                Install the package in the current Blender Python environment using pip, with target set to the lib directory.
                """
                try:
                    py_exec = str(sys.executable)
                    # Get lib directory
                    lib_dir = os.path.join(Path(py_exec).parent.parent, "lib")
                    # Ensure pip is available
                    subprocess.call([py_exec, "-m", "ensurepip", "--user"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                    # Upgrade pip (optional but recommended)
                    subprocess.call([py_exec, "-m", "pip", "install", "--upgrade", "pip"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                    # Install the package to the custom lib directory
                    subprocess.call([py_exec, "-m", "pip", "install", f"--target={str(lib_dir)}", package], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                    print(f"'{package}' has been installed.")
                    return f"'{package}' has been installed."
                except Exception as e:
                    print(f"Error installing '{package}': {e}")
                    return f"Error installing '{package}': {e}"

            def check_if_module_exists(module_name):
                """
                Check if a Python module is available without importing it.
                """
                return importlib.util.find_spec(module_name) is not None
            # List of required external packages
            required_packages = {
                'requests': 'requests',         # For making HTTP requests
                'opencv-python': 'cv2',         # For OpenCV (cv2)
                'gradio_client': 'gradio_client' # For using Gradio client
            }
            # Check and install missing packages
            missing_packages = []
            for package_name, module_name in required_packages.items():
                if not check_if_module_exists(module_name):
                    print(f"Module '{module_name}' is missing, will install '{package_name}'")
                    missing_packages.append(package_name)
            # Variable to track if any module was installed
            modules_installed = False
            # Install missing packages
            if missing_packages:
                modules_installed = True  # Mark that modules have been installed
                for package in missing_packages:
                    install_package(package)
            # If modules were installed, notify the user to restart Blender
            dependency_info = [admin_status_message]
            if modules_installed:
                dependency_info.append("Modules installed successfully. Please restart Blender.")
            # Store the result as a custom scene property in Blender
            bpy.context.scene['sna_dependency_info'] = "\n".join(dependency_info)
            # Output the result to the console
            print("\nDependency information stored in 'sna_dependency_info':")
            print(bpy.context.scene['sna_dependency_info'])
        # Run the install_dependencies function
        install_dependencies()
        self.report({'ERROR'}, message=bpy.context.scene.sna_dependency_info)
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


def sna_dependency_A098E(layout_function, ):
    box_39064 = layout_function.box()
    box_39064.alert = False
    box_39064.enabled = True
    box_39064.active = True
    box_39064.use_property_split = False
    box_39064.use_property_decorate = False
    box_39064.alignment = 'Expand'.upper()
    box_39064.scale_x = 1.0
    box_39064.scale_y = 1.0
    if not True: box_39064.operator_context = "EXEC_DEFAULT"
    row_08971 = box_39064.row(heading='', align=True)
    row_08971.alert = 'NOT' in bpy.context.scene.sna_dependency_info
    row_08971.enabled = True
    row_08971.active = True
    row_08971.use_property_split = False
    row_08971.use_property_decorate = False
    row_08971.scale_x = 1.0
    row_08971.scale_y = 1.0
    row_08971.alignment = 'Expand'.upper()
    row_08971.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    row_08971.label(text='Installation Info : ', icon_value=110)
    op = row_08971.operator('sn.dummy_button_operator', text='', icon_value=(36 if 'All required modules are installed.' in bpy.context.scene.sna_dependency_info else 3), emboss=False, depress=False)
    col_E819C = box_39064.column(heading='', align=True)
    col_E819C.alert = False
    col_E819C.enabled = True
    col_E819C.active = True
    col_E819C.use_property_split = False
    col_E819C.use_property_decorate = False
    col_E819C.scale_x = 1.0
    col_E819C.scale_y = 1.0
    col_E819C.alignment = 'Expand'.upper()
    col_E819C.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    box_51FF7 = col_E819C.box()
    box_51FF7.alert = False
    box_51FF7.enabled = True
    box_51FF7.active = True
    box_51FF7.use_property_split = False
    box_51FF7.use_property_decorate = False
    box_51FF7.alignment = 'Expand'.upper()
    box_51FF7.scale_x = 1.0
    box_51FF7.scale_y = 1.0
    if not True: box_51FF7.operator_context = "EXEC_DEFAULT"
    box_51FF7.prop(bpy.context.scene, 'sna_dependency_info', text='', icon_value=(36 if 'All required modules are installed.' in bpy.context.scene.sna_dependency_info else 3), emboss=False, expand=True)
    box_16BA8 = col_E819C.box()
    box_16BA8.alert = False
    box_16BA8.enabled = True
    box_16BA8.active = True
    box_16BA8.use_property_split = False
    box_16BA8.use_property_decorate = False
    box_16BA8.alignment = 'Expand'.upper()
    box_16BA8.scale_x = 1.100000023841858
    box_16BA8.scale_y = 1.100000023841858
    if not True: box_16BA8.operator_context = "EXEC_DEFAULT"
    col_8685E = box_16BA8.column(heading='', align=True)
    col_8685E.alert = 'NOT' in bpy.context.scene.sna_dependency_info
    col_8685E.enabled = True
    col_8685E.active = True
    col_8685E.use_property_split = False
    col_8685E.use_property_decorate = False
    col_8685E.scale_x = 1.0
    col_8685E.scale_y = 1.0
    col_8685E.alignment = 'Expand'.upper()
    col_8685E.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
    op = col_8685E.operator('sna.install_dependencies_3d3b5', text='Install Dependencies', icon_value=335, emboss=True, depress=False)
    op = box_16BA8.operator('sna.check_dependencies_70b8b', text='Check Dependency Installation', icon_value=30, emboss=True, depress=False)


class SNA_OT_Duplicate_Object_C2616(bpy.types.Operator):
    bl_idname = "sna.duplicate_object_c2616"
    bl_label = "duplicate_object"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        import os

        def apply_modifiers(obj):
            """
            Apply all modifiers of the object.
            """
            bpy.context.view_layer.objects.active = obj
            for modifier in obj.modifiers:
                try:
                    bpy.ops.object.modifier_apply(modifier=modifier.name)
                    print(f"Applied modifier: {modifier.name} on {obj.name}")
                except RuntimeError as e:
                    print(f"Error applying modifier '{modifier.name}' on '{obj.name}': {e}")

        def make_single_user(obj):
            """
            Make the object and all its data (mesh, materials, textures) single-user.
            """
            bpy.context.view_layer.objects.active = obj
            bpy.ops.object.make_single_user(type='SELECTED_OBJECTS', object=True, obdata=True, material=True, animation=False)
            print(f"Made object '{obj.name}' single-user.")

        def get_unique_image_path(filepath):
            """
            Generate a unique file path by appending a number to avoid overwriting existing images.
            """
            base, ext = os.path.splitext(filepath)
            counter = 1
            new_filepath = filepath
            # Loop until a unique file path is found
            while os.path.exists(new_filepath):
                new_filepath = f"{base}_{counter}{ext}"
                counter += 1
            return new_filepath

        def duplicate_image_and_link_to_texture_nodes():
            # Check if an object is selected
            obj = bpy.context.active_object
            if obj is None:
                print("No object selected.")
                return
            # Duplicate the selected object
            bpy.ops.object.duplicate()
            new_obj = bpy.context.active_object
            new_obj.name = obj.name + "_Duplicate"
            # Apply all modifiers
            apply_modifiers(new_obj)
            # Make the duplicated object single-user (object, mesh, materials)
            make_single_user(new_obj)
            # Get the blend file path and check if it's saved
            blend_file_path = bpy.data.filepath
            if not blend_file_path:
                print("Please save your Blender file before running the script.")
                return
            # Define paths
            base_dir = os.path.dirname(blend_file_path)
            images_dir = os.path.join(base_dir, 'generated_images')
            original_image_path = os.path.join(images_dir, "generated_image.png")
            # Ensure the image folder exists
            os.makedirs(images_dir, exist_ok=True)
            # Check if the original image exists
            if not os.path.exists(original_image_path):
                print(f"Original image not found at {original_image_path}")
                return
            # Generate a unique image path to avoid overwriting
            duplicated_image_path = get_unique_image_path(os.path.join(images_dir, "duplicated_generated_image.png"))
            # Duplicate the image
            try:
                shutil.copyfile(original_image_path, duplicated_image_path)
                print(f"Duplicated image to {duplicated_image_path}")
            except Exception as e:
                print(f"Error duplicating image: {e}")
                return
            # Load the duplicated image into Blender
            duplicated_image = bpy.data.images.load(duplicated_image_path)
            duplicated_image.name = os.path.basename(duplicated_image_path)
            # Link the duplicated image to all image texture nodes in the duplicated object's materials
            for material in new_obj.data.materials:
                if material and material.use_nodes:
                    for node in material.node_tree.nodes:
                        if node.type == 'TEX_IMAGE' and node.image:
                            # Assign the duplicated image
                            node.image = duplicated_image
                            print(f"Assigned duplicated image to texture node in material: {material.name}")
            # Pack the duplicated image into the blend file
            try:
                duplicated_image.pack()
                print(f"Packed duplicated image: {duplicated_image.name}")
            except RuntimeError as e:
                print(f"Error packing image: {e}")
            # Deselect the original object and select the new one
            bpy.context.view_layer.objects.active = new_obj
            obj.select_set(False)
            new_obj.select_set(True)
            print(f"Duplicated and modified object '{new_obj.name}' with linked and packed textures.")
        # Run the function
        duplicate_image_and_link_to_texture_nodes()
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Removedepthpath_A0955(bpy.types.Operator):
    bl_idname = "sna.removedepthpath_a0955"
    bl_label = "removedepthpath"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        bpy.context.scene.sna_depthpath = ' '
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Removenormalpath_52Ddd(bpy.types.Operator):
    bl_idname = "sna.removenormalpath_52ddd"
    bl_label = "removenormalpath"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        bpy.context.scene.sna_normalpath = ' '
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Removeallpath_Fbd35(bpy.types.Operator):
    bl_idname = "sna.removeallpath_fbd35"
    bl_label = "removeallpath"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Projectmat_B0596(bpy.types.Operator):
    bl_idname = "sna.projectmat_b0596"
    bl_label = "Projectmat"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        if property_exists("bpy.data.materials['ProjectMat']", globals(), locals()):
            pass
        else:
            before_data = list(bpy.data.materials)
            bpy.ops.wm.append(directory=os.path.join(os.path.dirname(__file__), 'assets', 'geonodesuvpack.blend') + r'\Material', filename='ProjectMat', link=False)
            new_data = list(filter(lambda d: not d in before_data, list(bpy.data.materials)))
            appended_A3C05 = None if not new_data else new_data[0]
        bpy.context.scene.sna_activeobject.modifiers['combine']['Socket_3'] = bpy.data.materials['ProjectMat']
        for i_BD18F in range(len(bpy.data.materials['ProjectMat'].node_tree.nodes)):
            if ('ShaderNodeTexImage' == bpy.data.materials['ProjectMat'].node_tree.nodes[i_BD18F].bl_idname):
                bpy.data.materials['ProjectMat'].node_tree.nodes[i_BD18F].image = bpy.context.scene.sna_outputimage
                print(bpy.data.materials['ProjectMat'].node_tree.nodes[i_BD18F].bl_idname, str(bpy.data.materials['ProjectMat'].node_tree.nodes[i_BD18F].image))
        bpy.context.scene.sna_activeobject.update_tag(refresh={'DATA'}, )
        if bpy.context and bpy.context.screen:
            for a in bpy.context.screen.areas:
                a.tag_redraw()
        bpy.ops.uv.textools_texture_reload_all('INVOKE_DEFAULT', )
        bpy.ops.image.reload('INVOKE_DEFAULT', )
        bpy.context.scene.sna_activeobject.update_tag(refresh={'DATA'}, )
        if bpy.context and bpy.context.screen:
            for a in bpy.context.screen.areas:
                a.tag_redraw()
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Combine_D06E8(bpy.types.Operator):
    bl_idname = "sna.combine_d06e8"
    bl_label = "combine"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        if property_exists("bpy.data.node_groups['combine']", globals(), locals()):
            pass
        else:
            before_data = list(bpy.data.node_groups)
            bpy.ops.wm.append(directory=os.path.join(os.path.dirname(__file__), 'assets', 'geonodesuvpack.blend') + r'\NodeTree', filename='combine', link=False)
            new_data = list(filter(lambda d: not d in before_data, list(bpy.data.node_groups)))
            appended_28205 = None if not new_data else new_data[0]
        if property_exists("bpy.context.scene.sna_activeobject.modifiers['combine']", globals(), locals()):
            pass
        else:
            modifier_593DC = bpy.context.scene.sna_activeobject.modifiers.new(name='combine', type='NODES', )
        bpy.context.scene.sna_activeobject.modifiers['combine'].node_group = bpy.data.node_groups['combine']
        bpy.ops.sna.projectmat_b0596('INVOKE_DEFAULT', )
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Mvgen_B6229(bpy.types.Operator):# 这个函数对场景进行生成6个视图.
    bl_idname = "sna.mvgen_b6229"
    bl_label = "mvgen"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('Please save your Blender file before running the script.')
        return not ('' == bpy.data.filepath)

    def execute(self, context):
        if ('' == bpy.data.filepath):
            self.report({'ERROR'}, message='Please save your Blender file before running the script.')
        else:
            if (None != bpy.context.view_layer.objects.active):
                if bpy.context.view_layer.objects.active.type == 'MESH':
                    bpy.context.scene.sna_activeobject = bpy.context.view_layer.objects.active
                    bpy.context.scene.sna_activeobject_name = bpy.context.scene.sna_activeobject.name
                    bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
                    if property_exists("bpy.data.node_groups['UV_New']", globals(), locals()):
                        pass
                    else:
                        before_data = list(bpy.data.node_groups)
                        bpy.ops.wm.append(directory=os.path.join(os.path.dirname(__file__), 'assets', 'geonodesuvpack.blend') + r'\NodeTree', filename='UV_New', link=False)
                        new_data = list(filter(lambda d: not d in before_data, list(bpy.data.node_groups)))
                        appended_4ED0B = None if not new_data else new_data[0]
                        bpy.context.view_layer.objects.active = bpy.context.scene.sna_activeobject
                    bpy.context.scene.sna_activeobject.select_set(state=True, )
                    modifier_5D814 = bpy.context.scene.sna_activeobject.modifiers.new(name='MV_Nodes', type='NODES', )
                    bpy.context.scene.sna_activeobject.modifiers['MV_Nodes'].node_group = bpy.data.node_groups['UV_New']
                    bpy.ops.object.convert(target='MESH', keep_original=True)
                    bpy.data.objects[bpy.context.scene.sna_activeobject_name].hide_render = True
                    bpy.ops.sna.aovbake_ad980('INVOKE_DEFAULT', )
                    bpy.data.objects[bpy.context.scene.sna_activeobject_name].modifiers.clear()
                    bpy.context.view_layer.objects[bpy.context.scene.sna_activeobject_name].hide_set(state=True, )
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Multibake_1Caf5(bpy.types.Operator):
    bl_idname = "sna.multibake_1caf5"
    bl_label = "MultiBake"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        bpy.data.objects[bpy.context.scene.sna_activeobject_name].hide_set(state=False, )
        bpy.data.objects[bpy.context.scene.sna_activeobject_name].hide_render = False
        bpy.context.scene.sna_activeobject.hide_set(state=False, )
        bpy.context.scene.sna_activeobject.hide_render = False
        if bpy.context and bpy.context.screen:
            for a in bpy.context.screen.areas:
                a.tag_redraw()
        # Set the target object for baking
        target_object_name = bpy.context.scene.sna_activeobject_name
        target_object = bpy.data.objects.get(target_object_name)
        if not target_object:
            raise ValueError(f"Target object '{target_object_name}' not found.")
        # Set the source object for baking
        source_object = bpy.context.scene.sna_activeobject
        if not source_object:
            raise ValueError("Source object is not defined in 'sna_activeobject'.")
        # Ensure the target object is in object mode
        bpy.ops.object.mode_set(mode='OBJECT')
        # Ensure the target object has a UV map
        if not target_object.data.uv_layers:
            target_object.data.uv_layers.new()
        # Bypass the emission material check for the source object
        print(f"Proceeding to set 'ProjectMat' for '{source_object.name}'.")
        # Assign "ProjectMat" as the active material for the source object
        project_mat = bpy.data.materials.get("ProjectMat")
        if project_mat:
            # Assign "ProjectMat" to the first material slot of the source object
            if source_object.data.materials:
                source_object.data.materials[0] = project_mat
            else:
                source_object.data.materials.append(project_mat)
            # Ensure the material is active
            source_object.active_material = project_mat
            print(f"'ProjectMat' assigned as active material to '{source_object.name}'.")
        else:
            print("Error: 'ProjectMat' material not found.")
        # Now perform optional baking (if you want to bake emission maps)
        # If not necessary, skip the following section

        def perform_bake():
            # Create a unique bake image
            bake_image_name = f"BakeImage_{source_object.name}"
            bake_image = bpy.data.images.get(bake_image_name)
            # Delete the existing image to avoid buffer issues
            if bake_image:
                bpy.data.images.remove(bake_image)
                print(f"Deleted existing bake image: {bake_image_name}")
            # Create a new bake image
            bake_image = bpy.data.images.new(bake_image_name, width=2048, height=2048)
            print(f"Created new bake image: {bake_image_name}")
            # Create a new material for baking
            bake_mat = bpy.data.materials.new(name=f"BakeMat_{source_object.name}")
            bake_mat.use_nodes = True
            nodes = bake_mat.node_tree.nodes
            links = bake_mat.node_tree.links
            # Clear existing nodes
            nodes.clear()
            # Create an emission node for baking
            emission_node = nodes.new(type='ShaderNodeEmission')
            # Create a material output node
            output_node = nodes.new(type='ShaderNodeOutputMaterial')
            output_node.location = 400, 0
            # Link emission node to output node
            links.new(emission_node.outputs['Emission'], output_node.inputs['Surface'])
            # Create an image texture node for the bake image
            image_node = nodes.new(type='ShaderNodeTexImage')
            image_node.location = -200, 0
            image_node.image = bake_image
            # Link the image node to the material's emission input
            links.new(image_node.outputs['Color'], emission_node.inputs['Color'])
            # Assign the bake material to the target object
            if target_object.data.materials:
                target_object.data.materials[0] = bake_mat
            else:
                target_object.data.materials.append(bake_mat)
            # Ensure the source and target objects are selected
            bpy.ops.object.select_all(action='DESELECT')
            source_object.select_set(True)
            target_object.select_set(True)
            bpy.context.view_layer.objects.active = target_object
            # Set bake settings
            bpy.context.scene.render.engine = 'CYCLES'
            bpy.context.scene.cycles.bake_type = 'EMIT'
            bpy.context.scene.cycles.samples = 8
            bpy.context.scene.render.bake.use_selected_to_active = True
            bpy.context.scene.render.bake.margin = 32
            # Perform the bake
            try:
                bpy.ops.object.bake(type='EMIT')
                print(f"Successfully baked emission from '{source_object.name}' to '{target_object.name}'.")
            except RuntimeError as e:
                print(f"Error during baking from {source_object.name}: {e}")
                bpy.context.scene.sna_bakepath = ''  # Clear bake path if baking fails
                bpy.context.scene.sna_bakeduv = None  # Clear baked UV if baking fails
                return
            # Save the baked image
            bake_image_filepath = f"//baked_emission_{source_object.name}.png"
            bake_image.filepath_raw = bake_image_filepath
            bake_image.file_format = 'PNG'
            bake_image.save()
            # Store the image path in Blender's scene context
            bpy.context.scene.sna_bakepath = bake_image_filepath
            print(f"Baked image saved to: {bake_image_filepath}")
            # Store the baked image as a Blender property
            bpy.context.scene.sna_bakeduv = bake_image
            # Create a new material with the baked image
            baked_image_mat = bpy.data.materials.new(name=f"BakedImageMat_{source_object.name}")
            baked_image_mat.use_nodes = True
            nodes = baked_image_mat.node_tree.nodes
            links = baked_image_mat.node_tree.links
            # Clear existing nodes
            nodes.clear()
            # Create an image texture node and assign the baked image
            image_node = nodes.new(type='ShaderNodeTexImage')
            image_node.image = bake_image
            # Create a diffuse BSDF shader node
            diffuse_node = nodes.new(type='ShaderNodeBsdfDiffuse')
            # Create a material output node
            output_node = nodes.new(type='ShaderNodeOutputMaterial')
            output_node.location = 400, 0
            # Link the image texture node to the diffuse shader, and then to the material output
            links.new(image_node.outputs['Color'], diffuse_node.inputs['Color'])
            links.new(diffuse_node.outputs['BSDF'], output_node.inputs['Surface'])
            # Assign the new material with the baked image to the target object
            if target_object.data.materials:
                target_object.data.materials[0] = baked_image_mat
            else:
                target_object.data.materials.append(baked_image_mat)
            print(f"Assigned baked image as material to '{target_object.name}'.")
        # Uncomment this if you need to perform baking
        perform_bake()
        print("Process completed: 'ProjectMat' assigned successfully.")
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Multiduplicate_464Eb(bpy.types.Operator):
    bl_idname = "sna.multiduplicate_464eb"
    bl_label = "MultiDuplicate"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        bpy.context.scene.sna_activeobject.active_material = bpy.data.materials['ProjectMat']
        bpy.context.scene.sna_activeobject.modifiers['combine']['Socket_7'] = bpy.data.materials['ProjectMat']
        bake_paths = None

        def set_modifier_property(obj, modifier_name, property_name, value):
            """
            Set a property on a modifier and ensure the update is applied.
            """
            if modifier_name in obj.modifiers:
                modifier = obj.modifiers[modifier_name]
                if property_name in modifier:
                    modifier[property_name] = value
                    obj.modifiers.update()
                    bpy.context.view_layer.update()
                    return True
            return False
        # Ensure the active object is stored in the scene
        active_obj = bpy.context.scene.sna_activeobject
        if active_obj is None:
            raise ValueError("No active object stored in 'bpy.context.scene.sna_activeobject'.")
        # Ensure the name attribute is stored in the scene
        bake_target_name = bpy.context.scene.sna_activeobject_name
        bake_target_obj = bpy.data.objects.get(bake_target_name)
        if bake_target_obj is None:
            raise ValueError(f"No object found with the name '{bake_target_name}'.")
        # Create a new collection for the duplicates if it doesn't already exist
        collection_name = "DuplicateCollection"
        if collection_name not in bpy.data.collections:
            duplicate_collection = bpy.data.collections.new(collection_name)
            bpy.context.scene.collection.children.link(duplicate_collection)
        else:
            duplicate_collection = bpy.data.collections[collection_name]
        # Duplicate the object 6 times and place them into the collection
        duplicates = []
        for i in range(6):
            # Ensure the active object is selected and active
            bpy.ops.object.select_all(action='DESELECT')
            active_obj.select_set(True)
            bpy.context.view_layer.objects.active = active_obj
            # Duplicate the object
            bpy.ops.object.duplicate()
            dup_obj = bpy.context.object
            # Ensure the duplication was successful
            if dup_obj:
                # Unlink from the original collection and link to the new one
                for collection in dup_obj.users_collection:
                    collection.objects.unlink(dup_obj)
                duplicate_collection.objects.link(dup_obj)
                duplicates.append(dup_obj)
            else:
                raise RuntimeError(f"Failed to duplicate the object on iteration {i}.")
        # Ensure context is updated before proceeding
        bpy.context.view_layer.update()
        # Loop over the objects in the collection to update the modifier values
        for i, dup_obj in enumerate(duplicates):
            # Update the modifier property for each object in the collection
            success = set_modifier_property(dup_obj, "combine", "Socket_5", i)
            if success:
                print(f"Updated {dup_obj.name} 'Socket_5' to {i}")
            else:
                print(f"Failed to update 'Socket_5' on {dup_obj.name}. Modifier or property not found.")
            # Tag the duplicate object for update on each iteration
            dup_obj.data.update_tag()
            dup_obj.update_tag(refresh={'OBJECT', 'DATA'})
            bpy.context.view_layer.update()
        # Optional: Reset the active object to the original after the operation
        bpy.context.view_layer.objects.active = active_obj
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Combinemaps_F255E(bpy.types.Operator):
    bl_idname = "sna.combinemaps_f255e"
    bl_label = "CombineMaps"
    bl_description = ""
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        print(str(layers['sna_bakepaths']))
        paths = layers['sna_bakepaths']
        bakepaths = None
        # Access the stored image paths from the previous script
        # Assuming that layers['sna_bakepaths'] is already populated
        bakepaths = layers['sna_bakepaths']
        # Debug: Print the bake paths to ensure they are correctly retrieved
        print("Bake paths:", bakepaths)
        # The name of the target object to which the new material will be assigned
        target_object_name = bpy.context.scene.sna_activeobject_name
        target_object = bpy.data.objects.get(target_object_name)
        if not target_object:
            raise ValueError(f"Target object '{target_object_name}' not found.")
        # Create a new material
        new_material = bpy.data.materials.new(name="BakedTexturesMaterial")
        # Enable 'use_nodes' within an appropriate context
        bpy.context.view_layer.objects.active = target_object  # Ensure the target object is active
        if not target_object.active_material:  # Add a new material slot only if needed
            bpy.ops.object.material_slot_add()
        target_object.active_material = new_material  # Assign the new material to the active slot
        # Now safely enable nodes
        new_material.use_nodes = True
        # Access the node tree of the new material
        nodes = new_material.node_tree.nodes
        links = new_material.node_tree.links
        # Clear existing nodes
        nodes.clear()
        # Create a Material Output node
        material_output = nodes.new(type='ShaderNodeOutputMaterial')
        material_output.location = (600, 0)
        # Initialize previous_node to None
        previous_node = None
        # Loop through the paths stored in bakepaths
        for i, bake_image_filepath in enumerate(bakepaths):
            if not bake_image_filepath:
                print(f"Skipping empty bake path at index {i}.")
                continue
            bake_image_name = bake_image_filepath.split("/")[-1]
            bake_image = bpy.data.images.get(bake_image_name)
            # Debug: Verify that the image is loaded
            if not bake_image:
                print(f"Image '{bake_image_name}' not found in Blender data. Loading image from path.")
                bake_image = bpy.data.images.load(bake_image_filepath)
            if not bake_image:
                print(f"Failed to load image '{bake_image_filepath}'.")
                continue
            # Create an Image Texture node
            image_node = nodes.new(type='ShaderNodeTexImage')
            image_node.image = bake_image
            image_node.location = (-200, -200 * i)
            # Debug: Confirm node creation
            print(f"Created Image Texture node for '{bake_image_name}' at location {image_node.location}")
            if previous_node is None:
                # If this is the first image, connect it directly to the surface output
                links.new(image_node.outputs['Color'], material_output.inputs['Surface'])
                previous_node = image_node
                print(f"Connected '{bake_image_name}' directly to material output.")
            else:
                # Create a MixRGB node for adding the textures
                mix_node = nodes.new(type='ShaderNodeMixRGB')
                mix_node.blend_type = 'ADD'
                mix_node.inputs['Fac'].default_value = 1.0
                mix_node.location = (200 * i, 0)
                # Connect the previous node output to the first color input of the Mix node
                links.new(previous_node.outputs['Color'], mix_node.inputs['Color1'])
                # Connect the current image node output to the second color input of the Mix node
                links.new(image_node.outputs['Color'], mix_node.inputs['Color2'])
                # Update previous node to the current mix node
                previous_node = mix_node
                # Finally, link the mix node output to the material output
                links.new(mix_node.outputs['Color'], material_output.inputs['Surface'])
                print(f"Connected MixRGB node to material output for '{bake_image_name}'.")
        # Ensure the new material is assigned to the object
        if target_object.data.materials:
            target_object.data.materials[0] = new_material
        else:
            target_object.data.materials.append(new_material)
        print("New material with baked textures created and assigned to the object.")
        print(bakepaths)
        bpy.ops.uv.textools_texture_reload_all('INVOKE_DEFAULT', )
        bpy.ops.image.reload()
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_PT_CONTROLNET_CONNECTION_708A6(bpy.types.Panel):
    bl_label = ' Controlnet Connection'
    bl_idname = 'SNA_PT_CONTROLNET_CONNECTION_708A6'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = ''
    bl_order = 1
    bl_parent_id = 'SNA_PT_AUTOPAINTER_AI_0A434'
    bl_ui_units_x=0

    @classmethod
    def poll(cls, context):
        return not (False)

    def draw_header(self, context):
        layout = self.layout
        row_14CCB = layout.row(heading='', align=True)
        row_14CCB.alert = False
        row_14CCB.enabled = True
        row_14CCB.active = True
        row_14CCB.use_property_split = False
        row_14CCB.use_property_decorate = False
        row_14CCB.scale_x = 1.0
        row_14CCB.scale_y = 1.0
        row_14CCB.alignment = 'Expand'.upper()
        row_14CCB.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
        op = row_14CCB.operator('sna.removeallpath_fbd35', text='', icon_value=56, emboss=False, depress=False)

    def draw(self, context):
        layout = self.layout
        layout_function = layout
        sna_connection_37713(layout_function, )


class SNA_PT_STABLE_DIFFUSION_AI_GENERATION_BB868(bpy.types.Panel):
    bl_label = ' Stable Diffusion AI Generation'
    bl_idname = 'SNA_PT_STABLE_DIFFUSION_AI_GENERATION_BB868'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = ''
    bl_order = 2
    bl_parent_id = 'SNA_PT_AUTOPAINTER_AI_0A434'
    bl_ui_units_x=0

    @classmethod
    def poll(cls, context):
        return not (False)

    def draw_header(self, context):
        layout = self.layout
        op = layout.operator('sn.dummy_button_operator', text='', icon_value=841, emboss=True, depress=True)

    def draw(self, context):
        layout = self.layout
        box_A1056 = layout.box()
        box_A1056.alert = False
        box_A1056.enabled = True
        box_A1056.active = (not 'thread started' in bpy.context.scene.sna_currentstatus)
        box_A1056.use_property_split = False
        box_A1056.use_property_decorate = False
        box_A1056.alignment = 'Expand'.upper()
        box_A1056.scale_x = 1.0
        box_A1056.scale_y = 1.0
        if not True: box_A1056.operator_context = "EXEC_DEFAULT"
        box_3A7CB = box_A1056.box()
        box_3A7CB.alert = False
        box_3A7CB.enabled = True
        box_3A7CB.active = True
        box_3A7CB.use_property_split = False
        box_3A7CB.use_property_decorate = False
        box_3A7CB.alignment = 'Expand'.upper()
        box_3A7CB.scale_x = 1.0
        box_3A7CB.scale_y = 1.0
        if not True: box_3A7CB.operator_context = "EXEC_DEFAULT"
        split_764B5 = box_3A7CB.split(factor=0.75, align=False)
        split_764B5.alert = False
        split_764B5.enabled = True
        split_764B5.active = True
        split_764B5.use_property_split = False
        split_764B5.use_property_decorate = False
        split_764B5.scale_x = 1.0
        split_764B5.scale_y = 1.0
        split_764B5.alignment = 'Expand'.upper()
        if not True: split_764B5.operator_context = "EXEC_DEFAULT"
        split_764B5.label(text='Info : ' + bpy.context.scene.sna_currentstatus, icon_value=110)
        op = split_764B5.operator('sna.resetstatus_0d6c7', text='Refresh', icon_value=692, emboss=True, depress=False)
        box_3A7CB.progress(text='Progress', factor=bpy.context.scene.sna_statusfloat, type='RING' if False else 'BAR')
        col_52991 = box_A1056.column(heading='', align=True)
        col_52991.alert = False
        col_52991.enabled = (not 'File Handle' in bpy.context.scene.sna_currentstatus)
        col_52991.active = (not 'Sending request' in bpy.context.scene.sna_currentstatus)
        col_52991.use_property_split = False
        col_52991.use_property_decorate = False
        col_52991.scale_x = 1.0
        col_52991.scale_y = 1.0
        col_52991.alignment = 'Expand'.upper()
        col_52991.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
        layout_function = col_52991
        sna_aigen_C4C48(layout_function, )
        layout_function = col_52991
        sna_generate_B95E5(layout_function, )
        if property_exists("bpy.context.scene.sna_outputimage.is_missing", globals(), locals()):
            box_D8E24 = col_52991.box()
            box_D8E24.alert = False
            box_D8E24.enabled = True
            box_D8E24.active = True
            box_D8E24.use_property_split = False
            box_D8E24.use_property_decorate = False
            box_D8E24.alignment = 'Expand'.upper()
            box_D8E24.scale_x = 1.0
            box_D8E24.scale_y = 1.0
            if not True: box_D8E24.operator_context = "EXEC_DEFAULT"
            col_2A885 = box_D8E24.column(heading='Enhance Generated Image', align=True)
            col_2A885.alert = False
            col_2A885.enabled = True
            col_2A885.active = True
            col_2A885.use_property_split = False
            col_2A885.use_property_decorate = False
            col_2A885.scale_x = 1.0
            col_2A885.scale_y = 1.0
            col_2A885.alignment = 'Expand'.upper()
            col_2A885.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            col_2A885.label(text='AI Upscaler :', icon_value=421)
            box_37639 = col_2A885.box()
            box_37639.alert = False
            box_37639.enabled = True
            box_37639.active = True
            box_37639.use_property_split = False
            box_37639.use_property_decorate = False
            box_37639.alignment = 'Expand'.upper()
            box_37639.scale_x = 1.899999976158142
            box_37639.scale_y = 1.899999976158142
            if not True: box_37639.operator_context = "EXEC_DEFAULT"
            col_D9F66 = box_37639.column(heading='', align=False)
            col_D9F66.alert = False
            col_D9F66.enabled = True
            col_D9F66.active = True
            col_D9F66.use_property_split = False
            col_D9F66.use_property_decorate = False
            col_D9F66.scale_x = 1.0
            col_D9F66.scale_y = 1.0
            col_D9F66.alignment = 'Expand'.upper()
            col_D9F66.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_F4F43 = col_D9F66.row(heading='Model Type :', align=True)
            row_F4F43.alert = False
            row_F4F43.enabled = True
            row_F4F43.active = True
            row_F4F43.use_property_split = False
            row_F4F43.use_property_decorate = False
            row_F4F43.scale_x = 1.0
            row_F4F43.scale_y = 0.75
            row_F4F43.alignment = 'Expand'.upper()
            row_F4F43.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_F4F43.prop(bpy.context.scene, 'sna_upscaletype', text=' ', icon_value=0, emboss=True, expand=True)
            op = col_D9F66.operator('sna.upscaleimage_c0257', text='Upscale & Enhance Image Details', icon_value=844, emboss=True, depress=False)


class SNA_PT_BAKING_302DF(bpy.types.Panel):
    bl_label = 'Baking'
    bl_idname = 'SNA_PT_BAKING_302DF'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = ''
    bl_order = 45
    bl_options = {'DEFAULT_CLOSED'}
    bl_parent_id = 'SNA_PT_AUTOPAINTER_AI_0A434'
    bl_ui_units_x=0

    @classmethod
    def poll(cls, context):
        return not (False)

    def draw_header(self, context):
        layout = self.layout
        op = layout.operator('sn.dummy_button_operator', text='', icon_value=455, emboss=False, depress=False)

    def draw(self, context):
        layout = self.layout
        col_2757E = layout.column(heading='', align=True)
        col_2757E.alert = False
        col_2757E.enabled = True
        col_2757E.active = True
        col_2757E.use_property_split = False
        col_2757E.use_property_decorate = False
        col_2757E.scale_x = 1.0
        col_2757E.scale_y = 1.0
        col_2757E.alignment = 'Expand'.upper()
        col_2757E.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
        box_C627D = col_2757E.box()
        box_C627D.alert = False
        box_C627D.enabled = True
        box_C627D.active = True
        box_C627D.use_property_split = False
        box_C627D.use_property_decorate = False
        box_C627D.alignment = 'Expand'.upper()
        box_C627D.scale_x = 2.0
        box_C627D.scale_y = 2.0
        if not True: box_C627D.operator_context = "EXEC_DEFAULT"
        op = box_C627D.operator('sna.multibake_1caf5', text='Bake Image into Original UV', icon_value=132, emboss=True, depress=False)
        if property_exists("bpy.context.scene.sna_bakeduv.name", globals(), locals()):
            box_5DF0B = box_C627D.box()
            box_5DF0B.alert = False
            box_5DF0B.enabled = True
            box_5DF0B.active = True
            box_5DF0B.use_property_split = False
            box_5DF0B.use_property_decorate = False
            box_5DF0B.alignment = 'Expand'.upper()
            box_5DF0B.scale_x = 1.0
            box_5DF0B.scale_y = 1.0
            if not True: box_5DF0B.operator_context = "EXEC_DEFAULT"
            box_5DF0B.template_icon(icon_value=get_id_preview_id(bpy.data.images[bpy.context.scene.sna_bakeduv.name]), scale=4.0)
        op = col_2757E.operator('sna.duplicate_object_c2616', text='Duplicate  Selected Object', icon_value=20, emboss=True, depress=False)


class SNA_PT_INSTALL_DEPENDENCIES_14FFE(bpy.types.Panel):
    bl_label = 'Install Dependencies'
    bl_idname = 'SNA_PT_INSTALL_DEPENDENCIES_14FFE'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = ''
    bl_order = 0
    bl_parent_id = 'SNA_PT_AUTOPAINTER_AI_0A434'
    bl_ui_units_x=0

    @classmethod
    def poll(cls, context):
        return not (False)

    def draw_header(self, context):
        layout = self.layout
        op = layout.operator('sn.dummy_button_operator', text='', icon_value=(36 if 'All required modules are installed.' in bpy.context.scene.sna_dependency_info else 3), emboss=False, depress=False)

    def draw(self, context):
        layout = self.layout
        layout_function = layout
        sna_dependency_A098E(layout_function, )


class SNA_PT_CONTROLNET_LAYERS_2BE01(bpy.types.Panel):
    bl_label = ' Controlnet Layers'
    bl_idname = 'SNA_PT_CONTROLNET_LAYERS_2BE01'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = ''
    bl_order = 1
    bl_parent_id = 'SNA_PT_AUTOPAINTER_AI_0A434'
    bl_ui_units_x=0

    @classmethod
    def poll(cls, context):
        return not (False)

    def draw_header(self, context):
        layout = self.layout
        box_367D7 = layout.box()
        box_367D7.alert = True
        box_367D7.enabled = True
        box_367D7.active = True
        box_367D7.use_property_split = False
        box_367D7.use_property_decorate = False
        box_367D7.alignment = 'Expand'.upper()
        box_367D7.scale_x = 1.0
        box_367D7.scale_y = 1.0
        if not True: box_367D7.operator_context = "EXEC_DEFAULT"
        op = box_367D7.operator('sn.dummy_button_operator', text='', icon_value=844, emboss=True, depress=True)

    def draw(self, context):
        layout = self.layout
        box_49013 = layout.box()
        box_49013.alert = False
        box_49013.enabled = True
        box_49013.active = True
        box_49013.use_property_split = False
        box_49013.use_property_decorate = False
        box_49013.alignment = 'Expand'.upper()
        box_49013.scale_x = 1.0
        box_49013.scale_y = 1.0
        if not True: box_49013.operator_context = "EXEC_DEFAULT"
        if ('' == bpy.data.filepath):
            box_14E35 = box_49013.box()
            box_14E35.alert = True
            box_14E35.enabled = True
            box_14E35.active = True
            box_14E35.use_property_split = False
            box_14E35.use_property_decorate = False
            box_14E35.alignment = 'Expand'.upper()
            box_14E35.scale_x = 1.0
            box_14E35.scale_y = 1.0
            if not True: box_14E35.operator_context = "EXEC_DEFAULT"
            box_14E35.label(text='Please save your Blender file before running the script.', icon_value=0)
        col_A699D = box_49013.column(heading='', align=False)
        col_A699D.alert = False
        col_A699D.enabled = True
        col_A699D.active = True
        col_A699D.use_property_split = False
        col_A699D.use_property_decorate = False
        col_A699D.scale_x = 1.0
        col_A699D.scale_y = 1.0
        col_A699D.alignment = 'Expand'.upper()
        col_A699D.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
        box_79EE5 = col_A699D.box()
        box_79EE5.alert = False
        box_79EE5.enabled = True
        box_79EE5.active = True
        box_79EE5.use_property_split = False
        box_79EE5.use_property_decorate = False
        box_79EE5.alignment = 'Expand'.upper()
        box_79EE5.scale_x = 2.0
        box_79EE5.scale_y = 2.0
        if not True: box_79EE5.operator_context = "EXEC_DEFAULT"
        split_4FC35 = box_79EE5.split(factor=0.8499999642372131, align=True)
        split_4FC35.alert = False
        split_4FC35.enabled = True
        split_4FC35.active = True
        split_4FC35.use_property_split = False
        split_4FC35.use_property_decorate = False
        split_4FC35.scale_x = 1.0
        split_4FC35.scale_y = 1.0
        split_4FC35.alignment = 'Expand'.upper()
        if not True: split_4FC35.operator_context = "EXEC_DEFAULT"
        op = split_4FC35.operator('sna.mvgen_b6229', text='Generate Multiview Maps', icon_value=157, emboss=True, depress=False)
        op = split_4FC35.operator('sna.removeallpath_fbd35', text='', icon_value=21, emboss=True, depress=False)
        if os.path.exists(bpy.context.scene.sna_depthpath):
            box_56DF7 = col_A699D.box()
            box_56DF7.alert = False
            box_56DF7.enabled = True
            box_56DF7.active = True
            box_56DF7.use_property_split = False
            box_56DF7.use_property_decorate = False
            box_56DF7.alignment = 'Expand'.upper()
            box_56DF7.scale_x = 1.0
            box_56DF7.scale_y = 1.0
            if not True: box_56DF7.operator_context = "EXEC_DEFAULT"
            box_91A96 = box_56DF7.box()
            box_91A96.alert = False
            box_91A96.enabled = True
            box_91A96.active = True
            box_91A96.use_property_split = False
            box_91A96.use_property_decorate = False
            box_91A96.alignment = 'Expand'.upper()
            box_91A96.scale_x = 1.0
            box_91A96.scale_y = 1.0
            if not True: box_91A96.operator_context = "EXEC_DEFAULT"
            split_3A28A = box_91A96.split(factor=0.27222222089767456, align=True)
            split_3A28A.alert = False
            split_3A28A.enabled = True
            split_3A28A.active = True
            split_3A28A.use_property_split = True
            split_3A28A.use_property_decorate = False
            split_3A28A.scale_x = 3.0
            split_3A28A.scale_y = 3.0
            split_3A28A.alignment = 'Left'.upper()
            if not True: split_3A28A.operator_context = "EXEC_DEFAULT"
            split_3A28A.template_icon(icon_value=get_id_preview_id(bpy.data.images[bpy.context.scene.sna_depthimage.name]), scale=1.2000000476837158)
            col_2ED4A = split_3A28A.column(heading='', align=False)
            col_2ED4A.alert = False
            col_2ED4A.enabled = True
            col_2ED4A.active = True
            col_2ED4A.use_property_split = False
            col_2ED4A.use_property_decorate = False
            col_2ED4A.scale_x = 0.5
            col_2ED4A.scale_y = 0.5
            col_2ED4A.alignment = 'Expand'.upper()
            col_2ED4A.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_DA4BE = col_2ED4A.row(heading='', align=True)
            row_DA4BE.alert = False
            row_DA4BE.enabled = True
            row_DA4BE.active = True
            row_DA4BE.use_property_split = False
            row_DA4BE.use_property_decorate = False
            row_DA4BE.scale_x = 1.0
            row_DA4BE.scale_y = 1.0
            row_DA4BE.alignment = 'Expand'.upper()
            row_DA4BE.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_DA4BE.prop(bpy.context.scene, 'sna_depthimage', text='', icon_value=0, emboss=True)
            op = row_DA4BE.operator('sna.removedepthpath_a0955', text='', icon_value=21, emboss=True, depress=False)
            row_13E8E = col_2ED4A.row(heading='', align=False)
            row_13E8E.alert = False
            row_13E8E.enabled = True
            row_13E8E.active = True
            row_13E8E.use_property_split = False
            row_13E8E.use_property_decorate = False
            row_13E8E.scale_x = 1.0
            row_13E8E.scale_y = 1.0
            row_13E8E.alignment = 'Expand'.upper()
            row_13E8E.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_13E8E.prop(bpy.context.scene, 'sna_depthpath', text='', icon_value=27, emboss=True, expand=True)
        if os.path.exists(bpy.context.scene.sna_normalpath):
            box_9A062 = col_A699D.box()
            box_9A062.alert = False
            box_9A062.enabled = True
            box_9A062.active = True
            box_9A062.use_property_split = False
            box_9A062.use_property_decorate = False
            box_9A062.alignment = 'Expand'.upper()
            box_9A062.scale_x = 1.0
            box_9A062.scale_y = 1.0
            if not True: box_9A062.operator_context = "EXEC_DEFAULT"
            box_8A92D = box_9A062.box()
            box_8A92D.alert = False
            box_8A92D.enabled = True
            box_8A92D.active = True
            box_8A92D.use_property_split = False
            box_8A92D.use_property_decorate = False
            box_8A92D.alignment = 'Expand'.upper()
            box_8A92D.scale_x = 1.0
            box_8A92D.scale_y = 1.0
            if not True: box_8A92D.operator_context = "EXEC_DEFAULT"
            split_C6510 = box_8A92D.split(factor=0.27222222089767456, align=True)
            split_C6510.alert = False
            split_C6510.enabled = True
            split_C6510.active = True
            split_C6510.use_property_split = True
            split_C6510.use_property_decorate = False
            split_C6510.scale_x = 3.0
            split_C6510.scale_y = 3.0
            split_C6510.alignment = 'Left'.upper()
            if not True: split_C6510.operator_context = "EXEC_DEFAULT"
            split_C6510.template_icon(icon_value=get_id_preview_id(bpy.data.images[bpy.context.scene.sna_normalimage.name]), scale=1.2000000476837158)
            col_1486C = split_C6510.column(heading='', align=False)
            col_1486C.alert = False
            col_1486C.enabled = True
            col_1486C.active = True
            col_1486C.use_property_split = False
            col_1486C.use_property_decorate = False
            col_1486C.scale_x = 0.5
            col_1486C.scale_y = 0.5
            col_1486C.alignment = 'Expand'.upper()
            col_1486C.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_44753 = col_1486C.row(heading='', align=True)
            row_44753.alert = False
            row_44753.enabled = True
            row_44753.active = True
            row_44753.use_property_split = False
            row_44753.use_property_decorate = False
            row_44753.scale_x = 1.0
            row_44753.scale_y = 1.0
            row_44753.alignment = 'Expand'.upper()
            row_44753.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_44753.prop(bpy.context.scene, 'sna_normalimage', text='', icon_value=0, emboss=True)
            op = row_44753.operator('sna.removenormalpath_52ddd', text='', icon_value=21, emboss=True, depress=False)
            row_99460 = col_1486C.row(heading='', align=False)
            row_99460.alert = False
            row_99460.enabled = True
            row_99460.active = True
            row_99460.use_property_split = False
            row_99460.use_property_decorate = False
            row_99460.scale_x = 1.0
            row_99460.scale_y = 1.0
            row_99460.alignment = 'Expand'.upper()
            row_99460.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_99460.prop(bpy.context.scene, 'sna_normalpath', text='', icon_value=27, emboss=True, expand=True)


def register():
    global _icons
    _icons = bpy.utils.previews.new()
    bpy.types.Scene.sna_urlwebui = bpy.props.StringProperty(name='urlwebui', description='', default='http://127.0.0.1:7860', subtype='NONE', maxlen=0)
    bpy.types.Scene.sna_inputprompt = bpy.props.StringProperty(name='inputprompt', description='', default=' 3d model, world of warcraft style', subtype='NONE', maxlen=0)
    bpy.types.Scene.sna_outputpath = bpy.props.StringProperty(name='outputpath', description='', options={'TEXTEDIT_UPDATE'}, default='', subtype='FILE_PATH', maxlen=0, update=sna_update_sna_outputpath_C4FC1)
    bpy.types.Scene.sna_outputimage = bpy.props.PointerProperty(name='outputimage', description='', type=bpy.types.Image)
    bpy.types.Scene.sna_activeobject = bpy.props.PointerProperty(name='activeobject', description='', type=bpy.types.Object)
    bpy.types.Scene.sna_activeobject_name = bpy.props.StringProperty(name='activeobject_name', description='', default='', subtype='NONE', maxlen=0)
    bpy.types.Scene.sna_depthpath = bpy.props.StringProperty(name='depthpath', description='', default='', subtype='FILE_PATH', maxlen=0, update=sna_update_sna_depthpath_2B6F0)
    bpy.types.Scene.sna_depthimage = bpy.props.PointerProperty(name='depthimage', description='', type=bpy.types.Image)
    bpy.types.Scene.sna_normalpath = bpy.props.StringProperty(name='normalpath', description='', default='', subtype='FILE_PATH', maxlen=0)
    bpy.types.Scene.sna_normalimage = bpy.props.PointerProperty(name='normalimage', description='', type=bpy.types.Image)
    bpy.types.Scene.sna_bakecam = bpy.props.PointerProperty(name='bakecam', description='', type=bpy.types.Object)
    bpy.types.Scene.sna_error = bpy.props.StringProperty(name='error', description='', default='', subtype='NONE', maxlen=0, update=sna_update_sna_error_28FD9)
    bpy.types.Scene.sna_availablemodels = bpy.props.EnumProperty(name='availablemodels', description='', items=sna_availablemodels_enum_items)
    bpy.types.Scene.sna_controlnet_installed = bpy.props.BoolProperty(name='controlnet_installed', description='', default=False)
    bpy.types.Scene.sna_controlnetnormal = bpy.props.EnumProperty(name='controlnetnormal', description='', items=sna_controlnetnormal_enum_items)
    bpy.types.Scene.sna_controlnetdepth = bpy.props.EnumProperty(name='controlnetdepth', description='', items=sna_controlnetdepth_enum_items)
    bpy.types.Scene.sna_resolution_multiplier = bpy.props.FloatProperty(name='resolution multiplier', description='', default=0.5, subtype='NONE', unit='NONE', min=0.20000000298023224, max=3.0, step=2, precision=2)
    bpy.types.Scene.sna_normal_weight = bpy.props.FloatProperty(name='normal weight', description='', default=1.0, subtype='NONE', unit='NONE', min=0.0, max=2.0, step=2, precision=2)
    bpy.types.Scene.sna_depth_weight = bpy.props.FloatProperty(name='depth weight', description='', default=1.0, subtype='NONE', unit='NONE', min=0.0, max=2.0, step=2, precision=2)
    bpy.types.Scene.sna_steps = bpy.props.IntProperty(name='steps', description='', default=20, subtype='NONE', min=5, max=80)
    bpy.types.Scene.sna_cfg_scale = bpy.props.FloatProperty(name='cfg scale', description='', default=7.0, subtype='NONE', unit='NONE', min=1.0, max=12.0, step=2, precision=2)
    bpy.types.Scene.sna_sd_model = bpy.props.StringProperty(name='sd model', description='', default='', subtype='NONE', maxlen=0)
    bpy.types.Scene.sna_controlnettype = bpy.props.EnumProperty(name='ControlnetType', description='', items=[('Cloud', 'Cloud', '', 671, 0), ('Local', 'Local', '', 634, 1)])
    bpy.types.Scene.sna_currentstatus = bpy.props.StringProperty(name='currentstatus', description='', default='', subtype='NONE', maxlen=0)
    bpy.types.Scene.sna_statusfloat = bpy.props.FloatProperty(name='statusfloat', description='', default=0.0, subtype='NONE', unit='NONE', step=2, precision=2, update=sna_update_sna_statusfloat_64985)
    bpy.types.Scene.sna_seed = bpy.props.IntProperty(name='seed', description='', default=0, subtype='NONE', min=0)
    bpy.types.Scene.sna_randomizeseed = bpy.props.BoolProperty(name='randomizeseed', description='', default=True)
    bpy.types.Scene.sna_progress_step = bpy.props.IntProperty(name='progress step', description='', default=0, subtype='NONE', update=sna_update_sna_progress_step_D1001)
    bpy.types.Scene.sna_bakepath = bpy.props.StringProperty(name='bakepath', description='', default='', subtype='NONE', maxlen=0)
    bpy.types.Scene.sna_bakeduv = bpy.props.PointerProperty(name='bakeduv', description='', type=bpy.types.Image)
    bpy.types.Scene.sna_dependency_info = bpy.props.StringProperty(name='dependency_info', description='', default='', subtype='NONE', maxlen=0)
    bpy.types.Scene.sna_error2 = bpy.props.StringProperty(name='error2', description='', default='', subtype='NONE', maxlen=0)
    bpy.types.Scene.sna_upscaletype = bpy.props.EnumProperty(name='UpscaleType', description='', items=[('FineGrain', 'FineGrain', '', 0, 0), ('Clarity', 'Clarity', '', 0, 1)])
    bpy.types.Scene.sna_cloudtype = bpy.props.EnumProperty(name='cloudtype', description='', items=[('Server 1 ', 'Server 1 ', '', 0, 0), ('Server 2 ', 'Server 2 ', '', 0, 1)])
    bpy.utils.register_class(SNA_PT_AUTOPAINTER_AI_0A434)
    bpy.utils.register_class(SNA_OT_Aovbake_Ad980)
    bpy.utils.register_class(SNA_OT_Cloudrender_C0123)
    bpy.utils.register_class(SNA_OT_Upscaleimage_C0257)
    bpy.utils.register_class(SNA_OT_Cloudrender2_63F36)
    bpy.utils.register_class(SNA_OT_Checkmodels_2E559)
    bpy.utils.register_class(SNA_OT_Ai_Render_4Aae9)
    bpy.utils.register_class(SNA_OT_Set_Sd_Model_2D717)
    bpy.utils.register_class(SNA_OT_Controlnettestserver_Bffa8)
    bpy.utils.register_class(SNA_OT_Resetstatus_0D6C7)
    bpy.utils.register_class(SNA_AddonPreferences_FE2DA)
    bpy.utils.register_class(SNA_OT_Check_Dependencies_70B8B)
    bpy.utils.register_class(SNA_OT_Install_Dependencies_3D3B5)
    bpy.utils.register_class(SNA_OT_Duplicate_Object_C2616)
    bpy.utils.register_class(SNA_OT_Removedepthpath_A0955)
    bpy.utils.register_class(SNA_OT_Removenormalpath_52Ddd)
    bpy.utils.register_class(SNA_OT_Removeallpath_Fbd35)
    bpy.utils.register_class(SNA_OT_Projectmat_B0596)
    bpy.utils.register_class(SNA_OT_Combine_D06E8)
    bpy.utils.register_class(SNA_OT_Mvgen_B6229)
    bpy.utils.register_class(SNA_OT_Multibake_1Caf5)
    bpy.utils.register_class(SNA_OT_Multiduplicate_464Eb)
    bpy.utils.register_class(SNA_OT_Combinemaps_F255E)
    bpy.utils.register_class(SNA_PT_CONTROLNET_CONNECTION_708A6)
    bpy.utils.register_class(SNA_PT_STABLE_DIFFUSION_AI_GENERATION_BB868)
    bpy.utils.register_class(SNA_PT_BAKING_302DF)
    bpy.utils.register_class(SNA_PT_INSTALL_DEPENDENCIES_14FFE)
    bpy.utils.register_class(SNA_PT_CONTROLNET_LAYERS_2BE01)


def unregister():
    global _icons
    bpy.utils.previews.remove(_icons)
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    for km, kmi in addon_keymaps.values():
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()
    del bpy.types.Scene.sna_cloudtype
    del bpy.types.Scene.sna_upscaletype
    del bpy.types.Scene.sna_error2
    del bpy.types.Scene.sna_dependency_info
    del bpy.types.Scene.sna_bakeduv
    del bpy.types.Scene.sna_bakepath
    del bpy.types.Scene.sna_progress_step
    del bpy.types.Scene.sna_randomizeseed
    del bpy.types.Scene.sna_seed
    del bpy.types.Scene.sna_statusfloat
    del bpy.types.Scene.sna_currentstatus
    del bpy.types.Scene.sna_controlnettype
    del bpy.types.Scene.sna_sd_model
    del bpy.types.Scene.sna_cfg_scale
    del bpy.types.Scene.sna_steps
    del bpy.types.Scene.sna_depth_weight
    del bpy.types.Scene.sna_normal_weight
    del bpy.types.Scene.sna_resolution_multiplier
    del bpy.types.Scene.sna_controlnetdepth
    del bpy.types.Scene.sna_controlnetnormal
    del bpy.types.Scene.sna_controlnet_installed
    del bpy.types.Scene.sna_availablemodels
    del bpy.types.Scene.sna_error
    del bpy.types.Scene.sna_bakecam
    del bpy.types.Scene.sna_normalimage
    del bpy.types.Scene.sna_normalpath
    del bpy.types.Scene.sna_depthimage
    del bpy.types.Scene.sna_depthpath
    del bpy.types.Scene.sna_activeobject_name
    del bpy.types.Scene.sna_activeobject
    del bpy.types.Scene.sna_outputimage
    del bpy.types.Scene.sna_outputpath
    del bpy.types.Scene.sna_inputprompt
    del bpy.types.Scene.sna_urlwebui
    bpy.utils.unregister_class(SNA_PT_AUTOPAINTER_AI_0A434)
    bpy.utils.unregister_class(SNA_OT_Aovbake_Ad980)
    bpy.utils.unregister_class(SNA_OT_Cloudrender_C0123)
    bpy.utils.unregister_class(SNA_OT_Upscaleimage_C0257)
    bpy.utils.unregister_class(SNA_OT_Cloudrender2_63F36)
    bpy.utils.unregister_class(SNA_OT_Checkmodels_2E559)
    bpy.utils.unregister_class(SNA_OT_Ai_Render_4Aae9)
    bpy.utils.unregister_class(SNA_OT_Set_Sd_Model_2D717)
    bpy.utils.unregister_class(SNA_OT_Controlnettestserver_Bffa8)
    bpy.utils.unregister_class(SNA_OT_Resetstatus_0D6C7)
    bpy.utils.unregister_class(SNA_AddonPreferences_FE2DA)
    bpy.utils.unregister_class(SNA_OT_Check_Dependencies_70B8B)
    bpy.utils.unregister_class(SNA_OT_Install_Dependencies_3D3B5)
    bpy.utils.unregister_class(SNA_OT_Duplicate_Object_C2616)
    bpy.utils.unregister_class(SNA_OT_Removedepthpath_A0955)
    bpy.utils.unregister_class(SNA_OT_Removenormalpath_52Ddd)
    bpy.utils.unregister_class(SNA_OT_Removeallpath_Fbd35)
    bpy.utils.unregister_class(SNA_OT_Projectmat_B0596)
    bpy.utils.unregister_class(SNA_OT_Combine_D06E8)
    bpy.utils.unregister_class(SNA_OT_Mvgen_B6229)
    bpy.utils.unregister_class(SNA_OT_Multibake_1Caf5)
    bpy.utils.unregister_class(SNA_OT_Multiduplicate_464Eb)
    bpy.utils.unregister_class(SNA_OT_Combinemaps_F255E)
    bpy.utils.unregister_class(SNA_PT_CONTROLNET_CONNECTION_708A6)
    bpy.utils.unregister_class(SNA_PT_STABLE_DIFFUSION_AI_GENERATION_BB868)
    bpy.utils.unregister_class(SNA_PT_BAKING_302DF)
    bpy.utils.unregister_class(SNA_PT_INSTALL_DEPENDENCIES_14FFE)
    bpy.utils.unregister_class(SNA_PT_CONTROLNET_LAYERS_2BE01)

posted on 2025-08-08 23:42  张博的博客  阅读(14)  评论(0)    收藏  举报

导航