Amending View Layers to track local render visibility

View Layers unfortunately don’t maintain all of the restriction toggle states. Instead, some of those states are applied globally across view layers. Toggling the collection/object properties listed below enacts the change across all View Layers (rather than just the active one).

hide_viewport
hide_render
hide_select

EDIT: As Robert points out below, these are all purposefully global. It would still be nice to have a local counterpart for renders.

Example

All attributes were previously disabled in the view layer ‘Disabled.’ Then I enabled all the attributes for the same object/collection in another view layer. If we return to ‘Disabled,’ some of its attributes have properly maintained their disabled state - except those that are highlighted below.

global_view_layer_props

Where I’m at

I’ve been researching Python solutions. My plan was to listen for attribute changes and persist them. Then use those persisted values to display proper attribute values when the view layer is changed.

But the blocker is how to listen to attribute changes. The solution might involve handlers.depsgraph_update_post - which looks promising for objects, but it doesn’t seem track collection data.

That is how the restriction toggles are supposed to work, hide in viewport is local and disable in viewports applies to all view layers.

If you want to solve this only for yourself and your particular use case, then you should take a look at bpy.msg_bus which could be a suitable solution.

1 Like

Much appreciated @Robert - good points.

It makes sense to have globally applied attributes in all three of those cases. The big issue is that there isn’t a local counterpart for render visibility.

Let’s say I have a scene with a cup and some coffee in it. Eventually I want to output a few renders (1) just the cup (2) just the coffee (3) cup and coffee. It’d be nice to split each of those situations into separate view layers and render each in turn. Currently, each of those view layers will require render visibility toggling before export. While that’s fine for simple projects, it doesn’t scale well to complex scenes - particularly when objects have conflicting settings in multiple view layers.

I use the checkmark toggle next to collections as a sort of local renderability.
So my workaround is to group objects I want to render or not render into collections, and toggle the collections with view layers.

But you really need to take care: toggling a collection on and off resets the visibility of ALL objects inside the collection. They don’t remember their state, which IMHO is a huge bug in the outliner, but that’s another topic.

Thanks again @Robert. I took a look at bpy.msg_bus - very useful for tracking property changes. Wondering if there would be a way to track function calls as well?

Explanation

With msg_bus, I can track:

(1) view layer ‘toggling’ (switching from one view layer to another)
subscribe_to = bpy.types.Window, "view_layer"
(2) view layer ‘renaming’
subscribe_to = bpy.types.ViewLayer, "name"

But I haven’t been able to track newly instantiated or removed view layers - perhaps because they use function calls. Related error:

subscribe_to = bpy.types.ViewLayers, "new"
TypeError: subscribe_rna: struct ViewLayers does not contain property new