123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- # ----------------------------------------------------------
- # File __init__.py
- # ----------------------------------------------------------
- # Imports
- # Check if this add-on is being reloaded
- if "bpy" in locals():
- # reloading .py files
- import bpy
- import importlib
- # from . import zs_renderscene as zsrs
- # importlib.reload(zsrs)
- # or if this is the first load of this add-on
- else:
- import bpy
- import json
- from pathlib import Path
- # from . import zs_renderscene as zsrs # noqa
- # Addon info
- bl_info = {
- "name": "ZS Stable Diffusion Connection V0.0.1",
- "author": "Sergiu <sergiu@zixelise.com>",
- "Version": (0, 0, 1),
- "blender": (4, 00, 0),
- "category": "Scene",
- "description": "Stable Diffusion Connection",
- }
- # -------------------------------------------------------------------
- # Functions
- # -------------------------------------------------------------------
- def load_scene():
- print("Loading Scene")
- # load scene data
- scene_data = load_scene_data()
- # create parent collections
- create_parent_collections("01_Products")
- create_parent_collections("02_Elements")
- create_parent_collections("03_Shapes")
- # append products
- products_data = load_objects_data(scene_data, "product")
- for index, product in enumerate(products_data):
- append_objects(product, index)
- # append elements
- # append shapes
- # set lighting
- # set camera
- def load_scene_data():
- print("Loading Scene Data")
- # load scene data
- # to be replaced with actual data
- # open scene_info.json
- script_path = Path(__file__).resolve()
- scene_data_path = script_path.parent / "sample_scene" / "scene_info.json"
- with scene_data_path.open() as file:
- scene_data = json.load(file)
- print(scene_data)
- return scene_data
- def load_objects_data(scene_data, object_type: str):
- print("Loading Assets Data")
- # load assets data
- objects_data = []
- for object in scene_data["scene"]["objects"]:
- if object["group_type"] == object_type:
- # get additional object data by id and combine with object data
- object_data = get_object_data_by_id(object["id"])
- object.update(object_data)
- objects_data.append(object)
- return objects_data
- # to be replaced with actual data
- def get_object_data_by_id(object_id: str):
- print("Getting Object Data")
- # open assets_database.json
- script_path = Path(__file__).resolve()
- assets_data_path = script_path.parent / "sample_scene" / "assets_database.json"
- with assets_data_path.open() as file:
- assets_data = json.load(file)
- # get object data by id
- for object in assets_data:
- if object["id"] == object_id:
- return object
- def append_objects(productInfo, index):
- print("Appending Objects")
- blendFileName = productInfo["name"]
- # visibleLayersJSONName = productInfo["Version"]
- # activeSwitchMaterials = json.dumps(productInfo["ActiveMaterials"])
- collectionName = blendFileName + "_" + str(index)
- append_active_layers(collectionName, productInfo)
- # replace_switch_materials(shotInfo, productInfo["ActiveMaterials"])
- link_collection_to_collection("01_Products", bpy.data.collections[collectionName])
- def append_active_layers(newCollectionName, product_info):
- utility_collections = ["MaterialLibrary", "Animation_Controller", "Animation_Rig"]
- # visible_layers = utility_collections + product_info["VisibleLayers"]
- visible_layers = utility_collections
- script_path = Path(__file__).resolve().parent
- filePath = str(
- script_path / product_info["path"] / (product_info["name"] + ".blend")
- )
- print(filePath)
- # delete all objects and collections from product collection
- create_parent_collections(newCollectionName)
- # append active collections
- with bpy.data.libraries.load(filePath) as (data_from, data_to):
- data_to.collections = []
- for name in data_from.collections:
- if name in visible_layers:
- data_to.collections.append(name)
- if "NonConfigurable" in name:
- data_to.collections.append(name)
- # link appended colections to newCollection
- for collection in data_to.collections:
- # try:
- # bpy.context.scene.collection.children.link(collection)
- # except:
- # print(collection)
- link_collection_to_collection(newCollectionName, collection)
- # hide utility collections
- for utilityCollectionName in utility_collections:
- if utilityCollectionName in collection.name:
- # rename utility collections
- collection.name = newCollectionName + "_" + utilityCollectionName
- hide_collection(collection)
- #
- # make all objects in collection local
- for obj in bpy.data.collections[newCollectionName].all_objects:
- if obj.type == "MESH":
- obj.make_local()
- obj.data.make_local()
- # remove duplicated material slots
- mats = bpy.data.materials
- for obj in bpy.data.collections[newCollectionName].all_objects:
- for slot in obj.material_slots:
- part = slot.name.rpartition(".")
- if part[2].isnumeric() and part[0] in mats:
- slot.material = mats.get(part[0])
- def create_parent_collections(group_name: str):
- if collection_exists(group_name):
- remove_collection_and_objects(group_name)
- else:
- create_collection(group_name)
- # -------------------------------------------------------------------
- # Utilities
- # -------------------------------------------------------------------
- def remove_collection_and_objects(collection_name):
- oldObjects = list(bpy.data.collections[collection_name].all_objects)
- for obj in oldObjects:
- bpy.data.objects.remove(obj, do_unlink=True)
- old_collection = bpy.data.collections[collection_name]
- if old_collection is not None:
- old_collection_names = get_subcollection_names(old_collection)
- else:
- print("Collection not found.")
- # print line break
- print("-----------------------------------------------------------------")
- print(old_collection_names)
- print("-----------------------------------------------------------------")
- for old_collection_name in old_collection_names:
- for collection in bpy.data.collections:
- if collection.name == old_collection_name:
- bpy.data.collections.remove(collection)
- bpy.ops.outliner.orphans_purge(
- do_local_ids=True, do_linked_ids=True, do_recursive=True
- )
- def get_subcollection_names(collection):
- subcollection_names = []
- for child in collection.children:
- subcollection_names.append(child.name)
- subcollection_names.extend(get_subcollection_names(child))
- return subcollection_names
- def link_collection_to_collection(parentCollectionName, childCollection):
- if bpy.context.scene.collection.children:
- parentCollection = bpy.context.scene.collection.children.get(
- parentCollectionName
- )
- # Add it to the main collection
- # childCollection = bpy.context.scene.collection.children.get(childCollection)
- parentCollection.children.link(childCollection)
- # if child collection is in scene collection unlink it
- if bpy.context.scene.collection.children.get(childCollection.name):
- bpy.context.scene.collection.children.unlink(childCollection)
- # bpy.context.scene.collection.children.unlink(childCollection)
- # link collection to collection
- def link_collection_to_collection_old(parentCollectionName, childCollection):
- if bpy.context.scene.collection.children:
- parentCollection = bpy.context.scene.collection.children.get(
- parentCollectionName
- )
- # Add it to the main collection
- try:
- childCollection = bpy.data.collections[childCollection]
- except:
- print("Collection not found.")
- return
- parentCollection.children.link(childCollection)
- bpy.context.scene.collection.children.unlink(childCollection)
- # function that checks if a collection exists
- def collection_exists(collection_name):
- return collection_name in bpy.data.collections
- # function that creates a new collection and adds it to the scene
- def create_collection(collection_name):
- new_collection = bpy.data.collections.new(collection_name)
- bpy.context.scene.collection.children.link(new_collection)
- def hide_collection(collection):
- collection.hide_render = True
- collection.hide_viewport = True
- # -------------------------------------------------------------------
- # Operators
- # -------------------------------------------------------------------
- # load scene operator
- class ZSSD_OT_LoadScene(bpy.types.Operator):
- bl_idname = "zs_sd_loader.load_scene"
- bl_label = "Load Scene"
- bl_description = "Load Scene"
- def execute(self, context):
- load_scene()
- return {"FINISHED"}
- # parent class for panels
- class ZSSDPanel:
- bl_space_type = "VIEW_3D"
- bl_region_type = "UI"
- bl_category = "ZS SD Loader"
- # -------------------------------------------------------------------
- # Draw
- # -------------------------------------------------------------------
- # Panels
- class ZSSD_PT_Main(ZSSDPanel, bpy.types.Panel):
- bl_label = "SD Loader"
- def draw(self, context):
- layout = self.layout
- scene = context.scene
- col = layout.column()
- self.is_connected = False
- col.label(text="Stable Diffusion Connection")
- # load scene button
- col.operator("zs_sd_loader.load_scene", text="Load Scene")
- # modify after making products
- blender_classes = [
- ZSSD_PT_Main,
- ZSSD_OT_LoadScene,
- ]
- def register():
- # register classes
- for blender_class in blender_classes:
- bpy.utils.register_class(blender_class)
- # Has to be afqter class registering to correctly register property
- # register global properties
- # register list
- # list data
- # bpy.types.Scene.zs_product_list = bpy.props.CollectionProperty(
- # type=ZS_Product_ListItem)
- # current item in list
- def unregister():
- # unregister classes
- for blender_class in blender_classes:
- bpy.utils.unregister_class(blender_class)
- # unregister global properties
- # unregister list items
- # del bpy.types.Scene.my_list
- # del bpy.types.Scene.product_product_list_index
|