2
$\begingroup$

I posted this on blenderartist.org, but to no avail.

I want to be able copy the Fcurve modifiers applied to ShapeKey drivers and paste them onto their counterparts on other objects, the other object's ShapeKey drivers.

This is manually quite simple to do; as in, you just copy the all the fcurve modifiers on a Driver from the graph editor, select the other object and again in the graph editor paste them whichever fcurve you want, in this case, its drivers... But with scripting in Blender, it turns out to be an enigma, whereas there is only the ability to add and remove an fmodifier to an fcurve, example:

bpy.data.shape_keys['Key'].animation_data.drivers[0].modifiers.new()
bpy.data.shape_keys['Key'].animation_data.drivers[0].modifiers.remove()

But bpy.ops.graph.fmodifier_copy() seems unbelievably tricky and seems not to play well within a script, like I think you need the area type to graph editor and invoke the command, which sounds pretty redundant.

And since the Blender API is almost totally devoid of real-world examples explaining the application of its commands and procedures, I'm totally stuck. I searched far and wide, even tried digging through other scripts.

How can I accomplish this task?

$\endgroup$

2 Answers 2

2
$\begingroup$

I don't think it is possible to get/set the active fcurve / driver. So you can not override the context for bpy.ops.graph.fmodifier_copy

You might use from_existing and adjust the data_path attribute from the returned driver accordingly if you want to copy the driver or try out this script:

import bpy

sk = bpy.data.shape_keys['Key']

source = sk.animation_data.drivers[0]
target = sk.animation_data.drivers[1]

for mod in source.modifiers:
    copy = target.modifiers.new(mod.type)
    for prop in mod.bl_rna.properties:
        if not prop.is_readonly:
            setattr(copy, prop.identifier, getattr(mod, prop.identifier))
$\endgroup$
1
  • $\begingroup$ My God Pink Vertex, you nailed it just right on the head... This is sublime... Very simple and to the point. The principle of this, I've been trying to do for the last 2 days but just couldn't come up with a viable solution. Very elegant solution and you just saved my day sir :) Thank you so very much for helping me out and hopefully others who will be seeking a solution to the very same problem in the future... $\endgroup$
    – jacobo
    Commented Oct 17, 2014 at 14:02
1
$\begingroup$

Ok, I've figured it out. Getting to the f-curve properties is a whole different kind of a method than getting to those of its f-modifier(s). Here's a sample of my code:

import bpy

aj = bpy.context.scene.objects.active
shape_key = aj.data.shape_keys
kbloks = shape_key.key_blocks.keys()
bpy.ops.object.duplicate()
ajDup = bpy.context.scene.objects.active

animParamList = [getattr(aj.data, 'shape_keys', None)] #form a list comprised of ShapeKeys on the active object
for anim in animParamList:
    if not anim or not anim.animation_data:
        continue
    action = anim.animation_data.action #If there are shapeKeys with f-curves, detect them    
    if action:
        #for each f-curve, get the data path, isolate the name, append it to an empty list, enumerate the entire list and isolate only the animated ones' names
        m = 0
        for fc in action.fcurves:
            AnimShps = []
            animfcrvDP = fc.data_path
            animfcrvChName=animfcrvDP.split('"')[1]
            AnimShps.append(animfcrvChName)
            AnimShpIndL = [i for i, j in enumerate(kbloks) if j == animfcrvChName]
            AnimShpInd = AnimShpIndL[0]
            bpy.context.object.active_shape_key_index = AnimShpInd

            ajDup.data.shape_keys.key_blocks[AnimShpInd].keyframe_insert("value")
            AjDuplFcrv = ajDup.data.shape_keys.animation_data.action.fcurves               
            AjDuplFcrv[m].keyframe_points.add(count=len(fc.keyframe_points)-1)

            k=0
            for key in AjDuplFcrv[m].keyframe_points: #get all the pertinent properties from the fcurves on the master object, iterate through and pass them onto their counterparts on the other object
                key.co = fc.keyframe_points[k].co
                key.interpolation = fc.keyframe_points[k].interpolation
                key.handle_left = fc.keyframe_points[k].handle_left
                key.handle_left_type = fc.keyframe_points[k].handle_left_type
                key.handle_right = fc.keyframe_points[k].handle_right
                key.handle_right_type = fc.keyframe_points[k].handle_right_type
                k+=1                
        m+=1
$\endgroup$

You must log in to answer this question.

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