Skip to content

plugin_load

add_override(loaded_collection)

Add overrides for the loaded armatures.

Source code in client/ayon_blender/api/plugin_load.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def add_override(
    loaded_collection: bpy.types.Collection,
) -> bpy.types.Collection:
    """Add overrides for the loaded armatures."""
    overridden_collections = list(
        get_overridden_collections_from_reference_collection(loaded_collection)
    )
    context = bpy.context
    scene = context.scene
    loaded_objects = loaded_collection.all_objects
    # This slightly convoluted way of running the operator seems necessary to
    # have it work reliably for more than 1 rig on both Linux and Windows.
    # Giving it a 'random' object from the collection seems to override
    # everything contained in the loaded collection.
    context.view_layer.objects.active = loaded_objects[0]

    from .plugin import create_blender_context  # todo: move import
    operator_context = create_blender_context(
        active=loaded_objects[0],
        selected=loaded_objects
    )

    # https://blender.stackexchange.com/questions/289245/how-to-make-a-blender-library-override-in-python  # noqa
    # https://docs.blender.org/api/current/bpy.types.ID.html#bpy.types.ID.override_hierarchy_create  # noqa
    if bpy.app.version[0] >= 4:
        with bpy.context.temp_override(**operator_context):
            loaded_collection.override_hierarchy_create(
                scene, context.view_layer, do_fully_editable=True
            )

    scene.collection.children.unlink(loaded_collection)

    if overridden_collections:
        local_collection = get_local_collection(
            overridden_collections,
            loaded_collection,
        )
    else:
        local_collection = loaded_collection

    return local_collection

get_local_collection(overridden_collections, loaded_collection)

Get the local (overridden) collection.

To get it we check all collections with a library override and check if they have the loaded collection as their reference. If a collection is not in the provided (known) override collections, we assume it's the newly created one.

Source code in client/ayon_blender/api/plugin_load.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
def get_local_collection(
    overridden_collections: list[bpy.types.Collection],
    loaded_collection: bpy.types.Collection,
) -> bpy.types.Collection:
    """Get the local (overridden) collection.

    To get it we check all collections with a library override and check if
    they have the loaded collection as their reference. If a collection is
    not in the provided (known) override collections, we assume it's the newly
    created one.
    """
    local_collections: set[bpy.types.Collection] = set()
    for collection in get_overridden_collections_from_reference_collection(
        loaded_collection
    ):
        if collection not in overridden_collections:
            local_collections.add(collection)
    if len(local_collections) != 1:
        raise RuntimeError("Could not find the overridden collection.")

    return local_collections.pop()

get_overridden_collections_from_reference_collection(reference_collection)

Get collections that are overridden versions of the reference collection.

Yields:

Type Description
Collection

All collections that have an override library and have the

Collection

reference_collection collection as reference.

Source code in client/ayon_blender/api/plugin_load.py
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def get_overridden_collections_from_reference_collection(
    reference_collection: bpy.types.Collection,
) -> Generator[bpy.types.Collection, None, None]:
    """Get collections that are overridden versions of the reference collection.

    Yields:
        All collections that have an override library and have the
        `reference_collection` collection as reference.
    """
    for collection in bpy.data.collections:
        if not collection.override_library:
            continue
        if collection.override_library.reference == reference_collection:
            yield collection

load_collection(filepath, link=True, lib_container_name=None, group_name=None)

Load a collection to the scene.

Source code in client/ayon_blender/api/plugin_load.py
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
140
141
142
143
def load_collection(
    filepath,
    link=True,
    lib_container_name = None,
    group_name = None
) -> bpy.types.Collection:
    """Load a collection to the scene."""
    loaded_containers = []
    asset_container = get_collection(group_name)
    with bpy.data.libraries.load(filepath, link=link, relative=False) as (
        data_from,
        data_to,
    ):
        for attr in dir(data_to):
            setattr(data_to, attr, getattr(data_from, attr))

    for coll in data_to.collections:
        if coll is not None and coll.name not in asset_container.children:
            asset_container.children.link(coll)

    for obj in data_to.objects:
        if obj is not None and obj.name not in asset_container.objects:
            asset_container.objects.link(obj)

    loaded_containers = [asset_container]

    if len(loaded_containers) != 1:
        for loaded_container in loaded_containers:
            bpy.data.collections.remove(loaded_container)
        raise LoadError(
            "More then 1 'container' is loaded. That means the publish was "
            "not correct."
        )
    container_collection = loaded_containers[0]

    return container_collection