import bpy import os def silence_puresky(): removed = 0 for handler_list in [bpy.app.handlers.depsgraph_update_pre, bpy.app.handlers.depsgraph_update_post]: for h in handler_list[:]: if "puresky" in str(h).lower() or "PureSky" in str(h): try: handler_list.remove(h) removed += 1 except Exception: pass return removed def fix_lib_overrides(): fixed = 0 for obj in bpy.data.objects: if not obj.modifiers: continue for mod in obj.modifiers: if mod.type != 'NODES' or not mod.node_group: continue if not hasattr(mod.node_group, 'interface'): continue ng = mod.node_group name_to_sid = {} iface = getattr(ng, 'interface', None) if iface and hasattr(iface, 'items_tree'): for item in iface.items_tree: if item.item_type == 'SOCKET' and item.in_out == 'INPUT': name_to_sid[item.name] = (item.identifier, item.socket_type) for item in (getattr(iface, 'items_tree', []) if iface else []): if item.item_type != 'SOCKET' or item.in_out != 'INPUT': continue sid = item.identifier if sid not in mod: continue stored = mod[sid] st = item.socket_type tt = type(stored).__name__ if st == 'NodeSocketBool' and tt == 'int': mod[sid] = bool(stored) fixed += 1 elif st == 'NodeSocketMenu' and tt == 'int': mod[sid] = int(stored) fixed += 1 ng_name = ng.name if ng_name == "Add Shader v1.0": if "Filter by ID" in name_to_sid: mod[name_to_sid["Filter by ID"][0]] = True fixed += 1 if "ID" in name_to_sid and name_to_sid["ID"][1] == "NodeSocketString": mod[name_to_sid["ID"][0]] = "Index" fixed += 1 elif ng_name in ["Add Shaders by Index v1.0", "Make Material", "Make Labels"]: if "ID" in name_to_sid and name_to_sid["ID"][1] == "NodeSocketString": mod[name_to_sid["ID"][0]] = "Index" fixed += 1 if ng_name == "Make Labels" and "Shrinkwrap" in name_to_sid: mod[name_to_sid["Shrinkwrap"][0]] = True fixed += 1 elif ng_name == "Make attached": if "Reset Children" in name_to_sid: mod[name_to_sid["Reset Children"][0]] = True fixed += 1 if "Separate Children" in name_to_sid: mod[name_to_sid["Separate Children"][0]] = True fixed += 1 elif ng_name == "Proxy v1.0": if "Reset Children" in name_to_sid: mod[name_to_sid["Reset Children"][0]] = True fixed += 1 return fixed def fix_missing_images(): fixed = 0 for img in bpy.data.images: if img.source == 'FILE' and img.filepath: if getattr(img, "packed_file", None): continue abs_path = (bpy.path.abspath(img.filepath, library=img.library) if img.library else bpy.path.abspath(img.filepath)) if not os.path.exists(abs_path): img.source = 'GENERATED' img.generated_width = 8 img.generated_height = 8 img.generated_type = 'BLANK' img.generated_color = (1.0, 0.0, 1.0, 1.0) fixed += 1 return fixed def init_metal_gpu(): try: prefs = bpy.context.preferences.addons['cycles'].preferences prefs.compute_device_type = 'METAL' prefs.get_devices() for dev in prefs.devices: dev.use = True return True except Exception: return False def get_scenes(): return [s.name for s in bpy.data.scenes if not s.name.startswith("_") and s.name != "_Shots"]