1
$\begingroup$

I am trying to copy the following driver in the Shape Keys section under Properties/Data: Look at the image below

enter image description here

When I right click it and go to copy driver it works, and it shows the command to be bpy.ops.anim.copy_driver_button() but if I run this command in the python shell it does not work. I know the problem has to be related to the context, so I tried to write an overrider dictionary and it is still not working:

window = bpy.context.window_manager.windows[0]
screen = window.screen
area = screen.areas[1]
region = area.regions[1]
space = area.spaces[0]
override = {'window': window, 'screen':screen, 'area':area, 'region':region, 'space_data':space}
bpy.ops.anim.copy_driver_button(override)

Now this does work if I bring up the command and I place my cursor over the purple button in the row where shape.L.000 (what I am trying to copy). If the cursor is not there it won't copy.I tried looking at the source code to see what is going on but that hasn't helped too much. Am I missing something in my override dictionary or is this doomed not to work? Any help would be greatly appreciated! Thanks

$\endgroup$
  • $\begingroup$ It may help to show a little more context into what your driver is calculating (where your driver properties are being watched). Because not all things drivers are fully implemented in Blender, the context of your calculation may have a lot to do with the solution on this question. $\endgroup$ – Rick Riggs Mar 29 '17 at 19:15
  • $\begingroup$ Hi @RickRiggs basically its controlling the z-component of a vertex in a cube. The driver is connected to an armature so when you translate the armature in the z-direction it raises the vertex in the mesh (the cube in this case). Basically the driver controls the following value: bpy.data.shape_keys["Key"].key_blocks["shape.L.000"].value $\endgroup$ – InsigMath Mar 29 '17 at 19:25
1
$\begingroup$

Okay this is a fairly simple solution then, I'm going to point you there instead of answer it yet, because I'm on my phone and not in front of blender (I will have to circle back around on this).

You need to get into the animation_data of your objects. This has driver, expression, and variable properties within. The big tip here is that you need to create a new variable before the expression will actually work. To get at these it's going to be something like:

bpy.data.objects["Cube"].animation_data


Here is a quick append to this answer for now to help you understand the data structure. However before you copy and apply this data to another object there is more to prepare on the "OTHER" object.

Still planning on circling back around on this to finalize this lacking part of the answer.

c1 = bpy.data.objects["C1"]
# This is the reference to my Original Cube with the Driver

dr1 = c1.animation_data.drivers
# This is the Driver collection of my Original Cube

dr1[0].data_path
# This returns 'scale'

dr1[0].expression
# This simply returns my expression 'var', because I am using a 1:1 mapping of another object's scale factor

dr1[0].driver.variables[0].name
# This returns the first (and only in this case) variable that I have named in this driver 'var'

dr1[0].driver.variables.items()[0][1].targets.items()[0][1].transform_type
# Returns 'SCALE_X'

dr1[0].driver.variables.items()[0][1].targets.items()[0][1].transform_space
# Returns 'WORLD_SPACE'

What the described code relates to

Without being able to confirm this yet, I'm going to recommend that you explore the following approach to get the copy:

For the sake of my code above, please follow my case (ultimately it should follow suit in yours).

I'm going to reference a second Cube whose name is "C2".

CONFIRMED

So for the prep on this object, before you can copy the data try:

c2 = bpy.data.object["C2"]

#If you were to create it manually -> c2.driver_add('scale', 0)
#Since you are copying do something like:

dr2_path = dr1[0].data_path
dr2_index = dr1[0].array_index
c2.driver_add(dr2_path, dr2_index)

#Now get reference to your new driver & Create a new Variable
dr2 = c2.animation_data.drivers
dr2[0].driver.variables.new()
#by default this should be 'var' if this is the 1st.
#You should now be able to copy the expression, target, etc... over from c1

dr2[0].driver.variables.items()[0][1].type = dr1[0].driver.variables.items()[0][1].type
dr2[0].driver.variables.items()[0][1].targets.items()[0][1].id = dr1[0].driver.variables.items()[0][1].targets.items()[0][1].id
dr2[0].driver.variables.items()[0][1].targets.items()[0][1].data_path = dr1[0].driver.variables.items()[0][1].targets.items()[0][1].data_path
dr2[0].driver.variables.items()[0][1].targets.items()[0][1].transform_type = dr1[0].driver.variables.items()[0][1].targets.items()[0][1].transform_type
dr2[0].driver.variables.items()[0][1].targets.items()[0][1].transform_space = dr1[0].driver.variables.items()[0][1].targets.items()[0][1].transform_space

Here's the proof of the rest of this code in play:

Proof of Driver Copy Result

$\endgroup$
  • $\begingroup$ This is a nonetype, are you sure this is the right expression? $\endgroup$ – InsigMath Mar 29 '17 at 20:10
  • $\begingroup$ @InsigMath Please see the latest append to the answer. Just not at a place where I can spend any time on this yet. $\endgroup$ – Rick Riggs Mar 29 '17 at 23:14
  • $\begingroup$ Thank you for the detailed answer, I will check this out when I have some time later today! $\endgroup$ – InsigMath Mar 30 '17 at 14:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.