I'm using python to create a blender scene; in that I'm setting up a driver for the opacity of a PrincipledBSDF based on two ShaderNodeValue nodes.

When I run it and load the resulting blendfile, I can see the driver working (I change opacity or component_opacity and the BSDF's alpha value changes appropriately), but I get errors about dependency cycles in Blender.

My code basically looks like this:

    opacity_value = mat.node_tree.nodes.new('ShaderNodeValue')
    opacity_value.name = 'opacity'
    opacity_value.label = 'opacity'
    for kf in sampled_kfs:
      opacity_value.outputs[0].default_value = kf.value[0]
      opacity_value.outputs[0].keyframe_insert('default_value', -1, kf.time)

    component_opacity_value = mat.node_tree.nodes.new('ShaderNodeValue')
    component_opacity_value.name = 'component_opacity'
    component_opacity_value.label = 'component_opacity'
    for kf in sampled_comp_opacity:
      component_opacity_value.outputs[0].default_value = kf.value[0]
      component_opacity_value.outputs[0].keyframe_insert('default_value', -1, kf.time)

    create_driver(mat.node_tree, path,
                  [{'name': 'opacity', 'target': mat.node_tree, 'target_type': 'NODETREE',
                    'path': 'nodes["opacity"].outputs[0].default_value'},
                   {'name': 'componentOpacity', 'target': mat.node_tree, 'target_type': 'NODETREE',
                    'path': 'nodes["component_opacity"].outputs[0].default_value'}],
                  'opacity * componentOpacity')

def create_driver(node, path, variables, expression):
  """Create a driver for path within the node, using the given variables.
  Each variable should be like `{name: "foo", type: "SINGLE_PROP", target: <obj>, target_type: 'OBJECT', path: "cp_foo"}`
  Expression is a simple string infix expression using the variable names, e.g. `foo*2`
  drv = node.driver_add(path).driver
  vars = {}
  for v in variables:
    name = v['name']
    vars[name] = drv.variables.new()
    vars[name].name = name
    vars[name].type = v.get('type', 'SINGLE_PROP')
    vars[name].targets[0].id_type = v.get('target_type', 'OBJECT')
    vars[name].targets[0].id = v['target']
    vars[name].targets[0].data_path = v['path']
  drv.expression = expression

The errors are like this:

Dependency cycle detected:
  NTShader Nodetree/Shading Component/MATERIAL_UPDATE() depends on
  NTShader Nodetree/Parameters Component/DRIVER(nodes["Principled BSDF"].inputs[19].default_value) via 'Driver -> Driven Property'
  NTShader Nodetree/Shading Component/MATERIAL_UPDATE() via 'RNA Target -> Driver'

I'm not creating a deliberate cycle; the BSDF's alpha input should be driven by the expression from the two values, which are keyframed. Seems straightforward, but I must be missing something. Any ideas how to debug this?

Here's a picture of what I'm trying to do: screenshot showing nodes and driver

  • $\begingroup$ Running Blender 2.93.0 alpha from March 29, on Linux, btw. $\endgroup$
    – GaryO
    May 25, 2021 at 16:19
  • $\begingroup$ What does path look like ? Could you post a working code example to test it out or a diagram of what you're trying to be driven by what ? $\endgroup$
    – Gorgious
    May 25, 2021 at 18:27
  • $\begingroup$ The whole thing is big, and has dependencies, but path within the shader node_tree is nodes["Principled BSDF"].inputs[19].default_value. That's the thing being driven. I added a diagram/screenshot. $\endgroup$
    – GaryO
    May 25, 2021 at 21:56
  • $\begingroup$ Have you considered using a math node to do the operation since you're using Value nodes ? $\endgroup$
    – Gorgious
    May 26, 2021 at 6:28
  • $\begingroup$ That is exactly what I ended up doing. Couldn't figure out why it said there was a circular dependency, so I switched to using nodes instead of drivers. I'd still like to know what I did wrong (or if there's a bug) but nodes do work fine for my case. $\endgroup$
    – GaryO
    May 26, 2021 at 9:52


You must log in to answer this question.

Browse other questions tagged .