RNA subscription can be global, or specific to an RNA instance depending on the key
passed it:
key = (bpy.types.View3DShading, "type") # Global key
A key that subscribes to any shading type of all view3d windows, present and future.
But, assuming we had an instance of View3DShading, sh
, we can create a subscription key that triggers only from this particular RNA:
sh = bpy.context.space_data.shading
key = sh.path_resolve("type", False) # Instance key
A key that subscribes to a shading type of a given View3DShading instance.
We then could pass the area in the args
keyword argument.
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
sh = area.spaces[0].shading
key = sh.path_resolve("type", False)
bpy.msgbus.subscribe_rna(key=key, owner=bpy, args=(area,), notify=notify_test,)
The downside of using instance keys, is that we have to do the bookkeeping ourselves, which means manually subscribing for each 3d view we would want this on, handle subscription to new areas created by the user, handle workspace changes, and remove invalid areas.
It’s certainly possible, but that’s a lot of code and cognitive overhead for something that should have been as simple as passing a set option to subscribe_rna
to get the instance along with any other argument.
Full example:
import bpy
def v3d_shading_notify(area):
sh = area.spaces.active.shading
index = area.id_data.areas[:].index(area)
print("area index", index,
"shading changed to", sh.type)
def register_shading_changes():
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
sh = area.spaces.active.shading
key = sh.path_resolve("type", False)
bpy.msgbus.subscribe_rna(
key=key,
owner=bpy,
args=(area,),
notify=v3d_shading_notify
)
if __name__ == "__main__":
bpy.msgbus.clear_by_owner(bpy)
register_shading_changes()