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:
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.
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
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
@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 )
it’s super annoying that there are so many things in the outliner that don’t have API access or parity. I just ran into this issue today where I needed to use msgbus to subscribe to a collection’s visibility. Out of the box the collection’s hide_viewport property isn’t even visible, so 10 out of 10 users are going to click the eyeball icon, which cannot be subscribed to since it doesn’t have a proper data path.
fantastic.
I’m glad we got so many outliner improvements, I’m not trying to be salty about it- but I wish when devs were adding features like this they kept it in the back of their mind that studios have pipelines to maintain and it makes it really hard to do that when they treat the api like an afterthought (if they think of it at all).
yeah that definitely works, part of my problem is that I needed to show specific collections in a UIList and there’s no easy way to get the CollectionLayer of a given collection, but once I wrote a recursive search it’s not really an issue anymore. Not the cleanest solution, mind you- but it works
recursive utility function for anyone who might need it:
def get_layer_collection(collection):
'''Returns the view layer LayerCollection for a specificied Collection'''
def scan_children(lc, result=None):
for c in lc.children:
if c.collection == collection:
return c
result = scan_children(c, result)
return result
return scan_children(bpy.context.view_layer.layer_collection)