Bases: BlenderExtractor, OptionalPyblishPluginMixin
Extract a blend file.
Source code in client/ayon_blender/plugins/publish/extract_blend.py
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 | class ExtractBlend(
plugin.BlenderExtractor, publish.OptionalPyblishPluginMixin
):
"""Extract a blend file."""
label = "Extract Blend"
hosts = ["blender"]
families = ["model", "camera", "rig", "layout", "blendScene"]
optional = True
# From settings
compress = False
def process(self, instance):
if not self.is_active(instance.data):
return
# Define extract output file path
stagingdir = self.staging_dir(instance)
folder_name = instance.data["folderEntity"]["name"]
product_name = instance.data["productName"]
instance_name = f"{folder_name}_{product_name}"
filename = f"{instance_name}.blend"
filepath = os.path.join(stagingdir, filename)
# Perform extraction
self.log.debug("Performing extraction..")
data_blocks = self.add_datablock(instance)
containers = list(ls())
with contextlib.ExitStack() as stack:
# If the instance node is a Collection, we want to enforce the
# full child hierarchies to be included in the written collections.
instance_node = instance.data["transientData"]["instance_node"]
if isinstance(instance_node, bpy.types.Collection):
# We only link children nodes to the 'parent' collection it is
# in so that the full children hierarchy is preserved for the
# main collection, and all its child collections.
collections = [instance_node]
collections.extend(instance_node.children_recursive)
for collection in set(collections):
missing_child_hierarchy = set()
for obj in collection.objects:
for child in obj.children_recursive:
if collection not in child.users_collection:
missing_child_hierarchy.add(child)
if missing_child_hierarchy:
stack.enter_context(link_to_collection(
collection, list(missing_child_hierarchy)))
stack.enter_context(strip_container_data(containers))
stack.enter_context(strip_namespace(containers))
self.log.debug("Datablocks: %s", data_blocks)
bpy.data.libraries.write(
filepath, data_blocks, compress=self.compress
)
if "representations" not in instance.data:
instance.data["representations"] = []
representation = {
'name': 'blend',
'ext': 'blend',
'files': filename,
"stagingDir": stagingdir,
}
instance.data["representations"].append(representation)
self.log.debug("Extracted instance '%s' to: %s",
instance.name, representation)
def add_datablock(self, instance: pyblish.api.Instance) -> set:
"""Add a data block to the blend file.
Args:
instance (pyblish.api.Instance): The instance to add.
Returns:
set: A set of data blocks added.
"""
data_blocks = set()
for data in instance:
data_blocks.add(data)
# Pack used images in the blend files.
if not (
isinstance(data, bpy.types.Object) and data.type == 'MESH'
):
continue
for material_slot in data.material_slots:
mat = material_slot.material
if not (mat and mat.use_nodes):
continue
tree = mat.node_tree
if tree.type != 'SHADER':
continue
for node in tree.nodes:
if node.bl_idname != 'ShaderNodeTexImage':
continue
# Check if image is not packed already
# and pack it if not.
if node.image and node.image.packed_file is None:
node.image.pack()
return data_blocks
|
Add a data block to the blend file.
Parameters:
| Name | Type | Description | Default |
instance | Instance | | required |
Returns:
| Name | Type | Description |
set | set | A set of data blocks added. |
Source code in client/ayon_blender/plugins/publish/extract_blend.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 | def add_datablock(self, instance: pyblish.api.Instance) -> set:
"""Add a data block to the blend file.
Args:
instance (pyblish.api.Instance): The instance to add.
Returns:
set: A set of data blocks added.
"""
data_blocks = set()
for data in instance:
data_blocks.add(data)
# Pack used images in the blend files.
if not (
isinstance(data, bpy.types.Object) and data.type == 'MESH'
):
continue
for material_slot in data.material_slots:
mat = material_slot.material
if not (mat and mat.use_nodes):
continue
tree = mat.node_tree
if tree.type != 'SHADER':
continue
for node in tree.nodes:
if node.bl_idname != 'ShaderNodeTexImage':
continue
# Check if image is not packed already
# and pack it if not.
if node.image and node.image.packed_file is None:
node.image.pack()
return data_blocks
|