3
$\begingroup$

I need a quick way to hide thousands of objects in the view layer via python. I have tried running the following code, but it takes 10 seconds to run with 10,000 objects:

objs_to_hide = bpy.context.scene.collection.all_objects
for obj in objs_to_hide:
    if obj.visible_get():
        obj.hide_set(True)

Is there a way to do this operation faster? I also tried using the 'hide_view_set' operator with the following code:

objs_to_hide = bpy.context.scene.collection.all_objects
for obj in objs_to_hide:
    obj.select_set(True)
bpy.context.view_layer.objects.active = objs_to_hide[0]
bpy.ops.object.hide_view_set(unselected=False)

But I got the following error when running that: RuntimeError: Operator bpy.ops.object.hide_view_set.poll() failed, context is incorrect

I have a feeling the operator would not be the most efficient path forwards anyways – operators seemingly rarely are. I did try hiding 10,000 objects from the viewport interface using the 'h' key and it seems to run instantly... which leads me to believe it must be possible to hide massive amounts of objects much faster than the first code snippet above. Any help would be greatly appreciated!

$\endgroup$

1 Answer 1

3
$\begingroup$

I'm not sure if it's applicable here, as you don't hide persistently for viewport/render, just hide temporarily as when using the H, but The docs say:

Object.hide_viewport, Object.hide_select and Object.hide_render: Setting any of those Booleans will trigger a rebuild of Collection caches, thus breaking any current iteration over Collection.all_objects.

Operators are slow when you call them on one object or just a handful of them, but they are very fast for bulk operations like this, because you move the loop from slow Python to fast C implementation.

import bpy
from bpy import context as C

for obj in C.scene.collection.all_objects:
    obj.select_set(True)

with C.temp_override(area=next(a for a in C.screen.areas if a.type=='VIEW_3D')):
    bpy.ops.object.hide_view_set()
$\endgroup$
6
  • $\begingroup$ @ChristopherGearhart I don't know an answer to that 🤔 $\endgroup$ Jun 3 at 18:29
  • $\begingroup$ Thank you! This works great, but after that code when I call bpy.context.space_data.overlay I now get the error EXCEPTION (<class 'AttributeError'>): 'NoneType' object has no attribute 'overlay', and it didn't used to error out. How do I revert the context back to the original state so I can access the overlay from the space data? $\endgroup$ Jun 3 at 18:30
  • 1
    $\begingroup$ @ChristopherGearhart deindent so you're no longer within with block. $\endgroup$ Jun 3 at 18:31
  • $\begingroup$ I also figured out how to achieve the same effect for unhiding only a select number of objects by building a list of all the hidden objects that I want to stay hidden (excluding objects that I want unhidden), running the bpy.ops.object.hide_view_clear() operator, and then running the bpy.ops.object.hide_view_set() operator again on the list of objects I built before unhiding all. $\endgroup$ Jun 3 at 18:32
  • $\begingroup$ It is deindendted but still errors out :/ $\endgroup$ Jun 3 at 18:36

You must log in to answer this question.

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