读懂这个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)