In Blender API there is a module that we can use to track the changes of any object’s properties available through the Python API. This module names “Message Bus”.
Let’s look at how we can make an event handler function to track changes to a property. For example – the location of the 3D cursor.
First, let’s define a simple function that will print to the system console (Main menu – Window – Toggle System Console) the current coordinates of the 3D cursor when they change.
1 2 3 4 |
import bpy def on_change_cursor_pos(*args): print(bpy.context.scene.cursor.location) |
The Message Bus works with the rna-structure of objects. So, to track a property using the Message Bus, we need to access the object through its type in “bpy.types”.
I the Blender API documentation we can find a description of the 3D cursor API type:
1 2 3 |
bpy.types.View3DCursor # <class 'bpy.types.View3DCursor'> |
Having received the desired type and knowing the name of the property that we want to track – “location”, we will sign the “on_change_cursor_pos” function defined above as a handler for tracking the position of the 3D cursor.
1 2 3 4 5 6 |
bpy.msgbus.subscribe_rna( key=(bpy.types.View3DCursor, 'location'), owner=bpy, args=('custom_arg_1', 'custrom_arg_2'), notify=on_change_cursor_pos ) |
In the “key” parameter, we pass the API type of the object and the name of the tracked property.
Optional additional arguments can be passed through the “args” parameter.
In the “notify” parameter, we specify our handler function that will be executed every time the property from the “key” parameter is changed.
Putting all the code together:
1 2 3 4 5 6 7 8 9 10 11 12 |
import bpy def on_change_cursor_pos(*args): print(bpy.context.scene.cursor.location) # print(args) bpy.msgbus.subscribe_rna( key=(bpy.types.View3DCursor, 'location'), owner=bpy, args=('custom_arg_1', 'custrom_arg_2'), notify=on_change_cursor_pos ) |
After executing this code, when the position of the 3D cursor is changed, its new coordinates will be displayed in the console.
Important limitations
The Message Bus is a powerful tool for tracking object properties in Blender. However, it has a very significant drawback – it works only through the object’s rna-structure, which means. that property change messages will be processed through the Message Bus only if the property is changed through the Blender interface or through the Python API.
If we move the 3D cursor by changing the values in the fields on the N-panel – our handler works fine.
It will also work if we set the coordinates of the 3D cursor through the API in the Python console:
1 |
bpy.context.scene.cursor.location = (1,0,0) |
However, the Message Bus will not work when we change the 3D cursor position with the mouse directly in the viewport window – by holding down the “shift” key and clicking the right mouse button, or, when the “Cursor” tool active, moving the cursor with the left mouse button!
Also, the Message Bus does not work when properties changed with animation curves!
* .blend file and python script with code for my Patreon subscribers
Very intresting!
I wonder if you know how i would write a script that prints out all actions taken? My use case is i want to record my workflow and create new python scripts recreating a whole scene,
There was a plugin for this earlier that doesnt work anymore and also some output is shown in console but its not complete enough to ”record” entire scene recreations.
Unfortunately, I think Blender does not provide for streaming of executable commands. it needs to think about how it can track all user actions. I think, that this is not a trivial task anyway.