Show/hide collection Blender Beta >= 2.80

I’m working with Blender’s beta 2.80 and have faced couple of issues trying the hide and show collection from Python. There is a lack of a robust API for doing that IMHO.

Please see what I mean. Currently we have only these three options for hiding a collection:

bpy.data.collections[0].hide_render
bpy.data.collections[0].hide_select
bpy.data.collections[0].hide_viewport

But Outliner has also the forth option with an opened/closed eye icon (the leftmost button compared to those three mentioned above).

There is two issues from my point of view:

  1. Description says that the eye hides object in viewport but the monitor disables object in viewport.
    At the same time the real scripting variable name for the latter is .hide_viewport which is a little bit confusing.

But it’s not a big deal though.

  1. There is no simple way to interact with the eye button to show and hide a collection from Python. But I finally found the one and just want to share it.
  • may be someone will find it helpful
  • may be Blender’s developers will add two distinct options like collection.hide_viewport and collection.disable_viewport :slight_smile:

So here is the code:

set_collection_viewport_visibility('some_collection_name')
set_collection_viewport_visibility('some_collection_name', visibility=False)
def get_viewport_ordered_collections(context):
    def fn(c, out, addme):
        if addme:
            out.append(c)
        for c1 in c.children:
            out.append(c1)
        for c1 in c.children:
            fn(c1, out, False)
    collections = []
    fn(context.scene.collection, collections, True)
    return collections

def get_area_from_context(context, area_type):
    area = None
    for a in context.screen.areas:
        if a.type == area_type:
            area = a
            break
    return area

def set_collection_viewport_visibility(context, collection_name, visibility=True):
    collections = get_viewport_ordered_collections(context)

    collection = None
    index = 0
    for c in collections:
        if c.name == collection_name:
            collection = c
            break
        index += 1

    if collection is None:
        return

    first_object = None
    if len(collection.objects) > 0:
        first_object = collection.objects[0]

    try:
        bpy.ops.object.hide_collection(context, collection_index=index, toggle=True)

        if first_object.visible_get() != visibility:
            bpy.ops.object.hide_collection(context, collection_index=index, toggle=True)
    except:
        context_override = context.copy()
        context_override['area'] = get_area_from_context(context, 'VIEW_3D')

        bpy.ops.object.hide_collection(context_override, collection_index=index, toggle=True)

        if first_object.visible_get() != visibility:
            bpy.ops.object.hide_collection(context_override, collection_index=index, toggle=True)

    return collection
5 Likes

Nothing to add, just wanted to say thank you for this. I’m sure I’ll need it one day.

Hi, Dmitriy. I tried your script and it’s didn’t work.

I imported your code like this it blender text editor

import bpy

def get_viewport_ordered_collections(context):
    def fn(c, out, addme):
        if addme:
            out.append(c)
        for c1 in c.children:
            out.append(c1)
        for c1 in c.children:
            fn(c1, out, False)
    collections = []
    fn(context.scene.collection, collections, True)
    return collections

def get_area_from_context(context, area_type):
    area = None
    for a in context.screen.areas:
        if a.type == area_type:
            area = a
            break
    return area

def set_collection_viewport_visibility(context, collection_name, visibility=True):
    collections = get_viewport_ordered_collections(context)
    collection = None
    index = 0
    for c in collections:
        if c.name == collection_name:
            collection = c
            break
        index += 1
    if collection is None:
        return
    first_object = None
    if len(collection.objects) > 0:
        first_object = collection.objects[0]
    try:
        bpy.ops.object.hide_collection(context, collection_index=index, toggle=True)
        if first_object.visible_get() != visibility:
            bpy.ops.object.hide_collection(context, collection_index=index, toggle=True)
    except:
        context_override = context.copy()
        context_override['area'] = get_area_from_context(context, 'VIEW_3D')
        bpy.ops.object.hide_collection(context_override, collection_index=index, toggle=True)
        if first_object.visible_get() != visibility:
            bpy.ops.object.hide_collection(context_override, collection_index=index, toggle=True)
    return collection

set_collection_viewport_visibility('High_poly', visibility=False)

The error is:

Traceback (most recent call last):
  File "\Collection hide", line 49, in <module>
TypeError: set_collection_viewport_visibility() missing 1 required positional argument: 'collection_name'
Error: Python script failed, check the message in the system console

@FeralMan Put
context = bpy.context
just after import bpy
And the last line should read
set_collection_viewport_visibility(context, 'YOUR_COLLECTION_NAME', visibility=False) (or True depending on what you want :grinning:)

1 Like
cols = bpy.context.view_layer.layer_collection.children
for col in cols:
  col.hide_viewport = True

doesn’t do nested collections eg. children of children though.