python unreliable result for bpy.context.view_layer.name when used in drivers #75553
Operating system: Linux-4.15.0-96-generic-x86_64-with-debian-buster-sid 64 Bits
Graphics card: GeForce GTX 980/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 430.50
Broken: version: 2.82 (sub 7), branch: master, commit date: 2020-03-12 05:06, hash:
Worked: Never (2.8+)
Short description of error
python gives unreliable results for bpy.context.view_layer.name when used in drivers
Exact steps for others to reproduce the error
1 Run the text script to record the python method isViewLayer1 for drivers
2 Edit the driver for the custum property "prop" in the scene panel (bottom right) -> shows invalid python expression (weird but not the core of the problem)
3 Press "update dependencies" -> gives result 1 as expected
4 Switch to "View Layer2" -> gives result 0 or 1 at random
5 Press "update dependencies" mulptiple time -> gives result 0 or 1 at random
For reference, this is the script:
import bpy from bpy.app.handlers import persistent from bpy.app import driver_namespace print (bpy.context.view_layer.name) @persistent def isViewLayer1(): if "View Layer 1" in bpy.context.view_layer.name: return 1 else: return 0 @persistent def load_handler(dummy): print("Load Handler") - dns = bpy.app.driver_namespace - register your drivers bpy.app.driver_namespace['isViewLayer1'] = isViewLayer1 def register(): print("Register") load_handler(None) bpy.app.handlers.load_pre.append(load_handler) bpy.app.handlers.load_post.append(load_handler) register()
Changed status from 'Needs Triage' to: 'Confirmed'
bpy.context from within a driver function is problematic, as it's unaware of which context is actually active at the time. For example, Blender could be rendering one view layer while displaying a different one in the 3D viewport.
bpy.context.view_layer depends on the current window to obtain the current view layer, so it will fail (by returning the default view layer) when there is no window. Why this happens seemingly randomly when updating the relations is still unknown to me.
The underlying issue is that the driver functions don't have access to the dependency graph. I have written #77086 (Passing Dependency Graph to Drivers) for this.
D8047: #77086 Animation: Passing Dependency Graph to Drivers has a fix for this issue. It just needs to be reviewed. In practice, this means that drivers will have a variable
depsgraph in their local scope, which should be passed to the function that needs it. So, the driver expression would be
isViewLayer1(depsgraph), and the function would be:
def isViewLayer1(depsgraph): return "View Layer 1" in depsgraph.view_layer.name
True == 1 and
False == 0, and
bool is actually a subclass of
int, so there is no need for the
return 0 construct ;-) )
By using the depsgraph that is passed to the driver, things keep working even when during rendering there are multiple view layers being evaluated at the same time.
Deleting a branch is permanent. Although the deleted branch may exist for a short time before cleaning up, in most cases it CANNOT be undone. Continue?