Blender 2.8 python hide / unhide objects

blender2-80

(sozap) #1

Hello,

I’d like to know if an object is hidden ( with H / Alt-H) or not , then make all objects visible, do some stuff and then hide them again.

I can get the object visibility state with ob.visible_get() , but it mixes hide_viewport and hide with H, and beside that it’s not possible to set the visibility back.

I’ve managed to unhide everything with some context override and bpy.ops.object.hide_view_clear(override)
But I hope there is a simpler way to do that…

Why I need that :
In my old script that I’m converting from 2.7 to 2.8, I do a bunch of operation on several objects, copy some vertex groups, add some modifier , apply modifiers ect… At some point I need to use bpy.ops.object… and the script fail if objects are hidden.

Thanks in advance !


(iceythe) #2

The ‘H’ operator sets a visibility flag for objects internally in blender, and isn’t accessible by the python API. I asked about this a few weeks ago on devtalk.

It’s possible to test the following by properties alone:

  • If an object is hidden using only ‘H’ (or the eye icon in outliner)
  • If an object is hidden with (at least) the monitor icon:

It’s not (yet) possible to distinguish if an object is hidden only with the monitor icon by property. However, you can toggle hide_viewport and re-test the object to determine if the visible_get() returns True, and if so you’ll know that it was hidden using only the monitor icon. Performance wise it shouldn’t have an impact since the scene isn’t redrawn until after the script, or if something in the script calls a redraw.

A quick example:

import bpy

# prints the name of hidden objects
def get_hidden():
    
    context = bpy.context

    with_eye = []
    with_monitor = []
    with_eye_and_monitor = []
    
    for o in context.view_layer.objects:
        
        if not o.hide_viewport and not o.visible_get():
            with_eye.append(o)
            continue
        
        if o.hide_viewport:
            o.hide_viewport = False # toggle to test visibility
            
            if o.visible_get():
                with_monitor.append(o)
                
            else:
                with_eye_and_monitor.append(o)
                
            o.hide_viewport = True # toggle back
        
    if with_eye:
        print(
            "With eye only:\n",
            [o.name for o in with_eye])
        
    if with_monitor:
        print(
            "With monitor only:\n",
            [o.name for o in with_monitor])
            
    if with_eye_and_monitor:
        print(
            "With eye and monitor:\n",
            [o.name for o in with_eye_and_monitor])
            
get_hidden()

As for hiding objects again with the appropriate setting;

Objects hidden with only hide_viewport only needs that property changed back.

Objects hidden with bpy.ops.object.hide_view_set(), however probably requires context override or selection by script, until the property this operator toggles is exposed.


(sozap) #3

Hey thanks a lot iceythe !!
Ok so there is not a simple way but it looks manageable !

thanks again for your time, this is much clearer now !


#4

Hi !

I have similar problem but I do not know how to override context. Do you remember how to do it?

Thanks in advance ! :slight_smile:


(BleuRaven) #5

I had the same problem for the collections but I found how to do with its two values
Bpy.data.collections [" MyCollectionName "] hide_viewport
bpy.context.view_layer.layer_collection.children [" MyCollectionName "] hide_viewport

But this work only with the collections
Do you have any idea when this property will be available for objects in the API?

I need unhide all objects and bpy.ops.object.hide_view_clear(select=False) return a error
RuntimeError: Operator bpy.ops.object.hide_view_clear.poll() failed, context is incorrect