6
$\begingroup$

I have read the answers to this question, so see you can access Geometry Nodes-generated attributes on an evaluated object using Python.

I'm attempting to access a mesh-wide vector-attribute in a driver. For testing purposes, a fixed vector value is plugged straight into the output node of a Geometry Nodes tree.

However, if I attempt to run v_attr(), a driver-namespace function, as defined below..

import bpy

def v_attr(obj_name, attr_name):
     
    C = bpy.context
    ob = bpy.data.objects [obj_name]
    ev_dg = C.evaluated_depsgraph_get()
    ev_me = ob.evaluated_get(ev_dg).data
    
    return ev_me.attributes[attr_name].data[0].vector

bpy.app.driver_namespace['v_attr'] = v_attr


#print(v_attr('Plane', 'v_test').y)

.. inside a driver, Blender 3.0b freezes.

Run from the Python console, v_attr() returns correct values, as a vector, or its components. Permission to auto-run scripts has been granted in Preferences.

I apologise if this is a premature question on a beta-bug, but I doubt that it is.. it's much more likely to be me, maybe misunderstanding the depsgraph altogether? Or permissions?

If there are better ways to store a mesh-wide attribute than duplicated on every point, that would be good...

$\endgroup$
10
  • $\begingroup$ may i ask where you added your driver to ? $\endgroup$
    – Chris
    Commented Nov 3, 2021 at 3:55
  • $\begingroup$ All the mesh attributes store the same value ? Because then you can use a custom property instead like you would on a regular object $\endgroup$
    – Gorgious
    Commented Nov 3, 2021 at 7:19
  • $\begingroup$ @chris I tried using v_attr('Plane', 'v_test').y in a scripted expression, to drive the Z location of an Empty. The result, for me, was a hang of (Linux) Blender 3.0b, requiring a kill of the Blender process. $\endgroup$
    – Robin Betts
    Commented Nov 3, 2021 at 8:02
  • $\begingroup$ @Gorgious I was just wondering if there was such a thing as a declared 'Whole Object' domain for an attribute, from within GN, which would save duplicating a value as a layer across all elements of a geometry domain. If I use, say, an Attribute Statistic result as an output, that may have to be stored only once, for the mesh. $\endgroup$
    – Robin Betts
    Commented Nov 3, 2021 at 8:10
  • $\begingroup$ @Gorgious sorry, that should be a 'Geometry' level domain: 1 attribute per hunk of geometry. $\endgroup$
    – Robin Betts
    Commented Nov 3, 2021 at 8:25

1 Answer 1

2
$\begingroup$

Not a full solution, but since Blender 2.90 you can use the depsgraph variable in drivers to retrieve the current dependency graph, which helps you avoid using bpy.context:

import bpy

def v_attr(ev_dg, obj_name, attr_name):
     
    ob = bpy.data.objects[obj_name]
    ev_me = ob.evaluated_get(ev_dg).data
    
    return ev_me.attributes[attr_name].data[0].vector

bpy.app.driver_namespace['v_attr'] = v_attr

Then in your driver function call, just add an argument depsgraph at the start.

However, even then, there is no depsgraph relation built between the mesh, which is why there is no automatic update (you must click on "Update Dependencies" on the driver to see changes).

Alternative implementation, without extending the driver namespace: bpy.data.objects["Plane"].evaluated_get(depsgraph).data.attributes["v_test"].data[0].vector.y. This warns about use of bpy.data, but there sadly is no way to retrieve an evaluated mesh through the driver variables.

$\endgroup$

You must log in to answer this question.

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