0
$\begingroup$

Here is a Driver. It is a Custom Property on an Object that is driving a value in a Shader Node. It was made by right clicking on the property and Copying as Driver. It uses a Variable. If I change the property's value, it updates instantly. This is working properly.

enter image description here

Here is an equivalent Driver accessing the same property, but this time its using the Full Data Path as an expression. It works, but it does not update in the viewport when the property's value is changed. It is the correct value when doing a F12 render. Updating Dependencies or reloading the file updates it.

enter image description here

I am trying to figure out how to get drivers to update in the UI instantly when using an expression like this. (The use case is Relative Path Drivers. I want to Drive based on a path to a property by name in the current file, not an absolute path to a specific property and target, which is what you get when using the variable system. In other words, if I drive based on World Color, I want it to be the World of the current file, not the asset's home file. See this question.)

There are a lot of questions out there related to Drivers not updating. Most of those are from before the new Dependency Graph that came in 2.8, so they don't apply.

So I need a way to have it automatically update, or I need to figure out how to Update Dependencies on everything. This is also a question that comes up. The usual method is to re-assign the existing expression to the Driver. This solves many update issues, and it solves this one on objects local to the file. But it does NOT work on Linked Objects, so cannot fully address the problem. Those can still be updated with the Update Dependency button, but their expression field is greyed out and cannot be modified.

How can I get expression drivers to update?

$\endgroup$

1 Answer 1

1
$\begingroup$

Similar to this button function but for all drivers

enter image description here

import bpy

# not include shape-key driver because they are not in animation_data.drivers
def update_driver(obj):
    try:
        for fc in obj.animation_data.drivers:
            fc.driver.expression = fc.driver.expression
    except:
        pass

for obj in bpy.data.objects:
    update_driver(obj)

update once when active object changed

import bpy

# not include shape-key driver because they are not in animation_data.drivers
def update_driver(obj):
    try:
        for fc in obj.animation_data.drivers:
            fc.driver.expression = fc.driver.expression
    except:
        pass


def when_active_object_changed():
    print("when_active_object_changed")
    for obj in bpy.data.objects:
        update_driver(obj)

owner = "owner"

bpy.msgbus.subscribe_rna(
    key     = (bpy.types.LayerObjects, 'active'),
    owner   = owner,
    args    = (),
    notify  = when_active_object_changed,
)

Live update, performance issues if there are too many objects in the scene, maybe it has a better solution

import bpy

# not include shape-key driver because they are not in animation_data.drivers
def update_driver(obj):
    try:
        for fc in obj.animation_data.drivers:
            fc.driver.expression = fc.driver.expression
    except:
        pass


def when_depsgraph_update(dummy):
    print("when_depsgraph_update")
    for obj in bpy.data.objects:
        update_driver(obj)

bpy.app.handlers.depsgraph_update_post.append(when_depsgraph_update)
$\endgroup$
4
  • $\begingroup$ This is working as an update, even on Linked Data! (In my case I had to change it from Objects to node_groups as that's where my drivers are). I would still like to find an answer to the update issue other than manually doing it with a script though. Perhaps there is some way to auto run this script on changes to certain property fields? $\endgroup$
    – Ascalon
    Commented Sep 10, 2022 at 18:04
  • $\begingroup$ Consider using bpy.msgbus to subscribe to the property ["obj_prop"], when this property value changed, it will update the driver. but still need to run the script once. $\endgroup$
    – X Y
    Commented Sep 10, 2022 at 18:58
  • $\begingroup$ @X Y Okay I have a basic msgbus setup that prints when the property changes, but I'm not quite sure how to use it. I take it I have it run the update script above instead of just print. $\endgroup$
    – Ascalon
    Commented Sep 11, 2022 at 6:59
  • $\begingroup$ Yes, you should just have it run the script above. In this case it is probably best to pack this code into an addon so it is run every time blender starts. You can subscribe to new properties by copying and pasting their datapath into an operator field of your choice. $\endgroup$
    – Tyler
    Commented Sep 11, 2022 at 14:43

You must log in to answer this question.

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