Skip to content

extract_blend

ExtractBlend

Bases: BlenderExtractor, OptionalPyblishPluginMixin

Extract a blend file.

Source code in client/ayon_blender/plugins/publish/extract_blend.py
 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
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)
        asset_group = instance.data["transientData"]["instance_node"]
        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_instance_data(asset_group))
            stack.enter_context(strip_namespace(containers))
            stack.enter_context(packed_images(data_blocks))
            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.
        """
        return set(instance)

add_datablock(instance)

Add a data block to the blend file.

Parameters:

Name Type Description Default
instance Instance

The instance to add.

required

Returns:

Name Type Description
set set

A set of data blocks added.

Source code in client/ayon_blender/plugins/publish/extract_blend.py
111
112
113
114
115
116
117
118
119
120
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.
    """
    return set(instance)

ExtractBlendAction

Bases: ExtractBlend

Extract a blend file from the current scene.

Source code in client/ayon_blender/plugins/publish/extract_blend.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
class ExtractBlendAction(ExtractBlend):
    """Extract a blend file from the current scene.
    """
    families = ["action"]
    label = "Extract Blend (Action)"
    optional = False
    # From settings
    compress = False

    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.
        """
        return {
            action for action in bpy.data.actions
            if action.name == instance.data["productName"]
        }

add_datablock(instance)

Add a data block to the blend file.

Parameters:

Name Type Description Default
instance Instance

The instance to add.

required

Returns:

Name Type Description
set set

A set of data blocks added.

Source code in client/ayon_blender/plugins/publish/extract_blend.py
131
132
133
134
135
136
137
138
139
140
141
142
143
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.
    """
    return {
        action for action in bpy.data.actions
        if action.name == instance.data["productName"]
    }

Link objects to a collection during context

Source code in client/ayon_blender/plugins/publish/extract_blend.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@contextlib.contextmanager
def link_to_collection(collection, objects):
    """Link objects to a collection during context"""
    unlink_after = []
    try:
        for obj in objects:
            if not isinstance(obj, bpy.types.Object):
                continue
            if collection not in obj.users_collection:
                unlink_after.append(obj)
                collection.objects.link(obj)
        yield
    finally:
        for obj in unlink_after:
            collection.objects.unlink(obj)