1
$\begingroup$

Wondering how I could switch a collection to "Indirect Only" in Blender 2.8 with Python.

So far I have found this:

bpy.ops.outliner.collection_indirect_only_set()

And this:

bpy.context.scene.indirect_only = True

As you can see none of these will work. As far as I understand it I need some kind of bpy.data function that would effectively allow me to choose which collection (using it's name, or "keys()") to set as Indirect Only.

$\endgroup$

2 Answers 2

2
$\begingroup$

You can enable Indirect Only for the currently active collection (as indicated in the outliner) by using:

bpy.context.view_layer.active_layer_collection.indirect_only = True
$\endgroup$
2
$\begingroup$

A previous answer is a good hint but felt a bit incomplete, so here is a more exhaustive one based on my current understanding of Blender and OP's question.

The pitfall

The UI might be misleading, but a Collection does not hold rendering properties such as indirect_only. Such properties, that might change from layer to layer, are actually stored through the ViewLayer and its LayerCollections. The LayerCollection encapsulates properties such as indirect_only, and a pointer to the Collection they apply to.

Proposed solution

So, now we can write a snippet of code that will programmatically change the value of indirect_only from a given Collection:

def iterate_layer_collections(view_layer):
    """Depth-first layer collections traversal"""
    stack = [view_layer.layer_collection]
    while stack:
        layer_collection = stack.pop()
        stack.extend(layer_collection.children)
        yield layer_collection


def set_render_attr(view_layer, collection, attribute, value):
    for layer_collection in iterate_layer_collections(view_layer):
        if layer_collection.collection != collection:
            continue  # Not the layer collection we are looking for
        setattr(layer_collection, attribute, value)

set_render_attr(
    bpy.context.view_layer,
    bpy.context.collection,
    "indirect_only",
    True,
)

Note on complexity

Note that in the code above, set_render_attr is looping over all the LayerCollections, so if you want to set this value for all the Collections in the scene, you will end up with $O(n)$ complexity, with $n$ the Collection count of your scene. Might be okay for a typical use case, but something to keep an eye on.

$\endgroup$
1
  • 1
    $\begingroup$ Excellent answer and thorough analysis. I would just note that if the current view layer scene collection contains linked collections, this solution will change the attribute of all the layer collections at once, which might not be desirable (for indirect only I assume this is desirable, but for other properties it might not be), see i.sstatic.net/hC2lH.png for an illustration of how you can set different properties to the same collection in two layer collections) and devtalk.blender.org/t/unique-identifier-for-layer-collections/… for why this problem matters (to me) $\endgroup$
    – Gorgious
    Mar 14, 2023 at 17:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .