2
$\begingroup$

I have been trying to figure out how to add the Noise fcurve modifier to a Simple Deform's angle parameter. When I attempt to do that, I get an error saying that the context is wrong.

I have also been looking through the documentation to see if I can change the value of Noise's offset to something random for each object selected. Since it's an f-curve modifier, I'm having trouble knowing how to go about that.

I'm new to programming so I'm sorry if this is a simple answer. I've been struggling so I would appreciate any help.

Thank you so much!

Code:

import bpy
import math
    def anim_bend(input_name, bend_angle):
        
        obj = bpy.context.active_object
        
        # for each selected object, run this
        for obj in bpy.data.objects:
            if input_name in obj.name:
                
                #select objects individually 
                ob = bpy.context.scene.objects[obj.name]     # get the object
                bpy.ops.object.select_all(action='DESELECT') # deselect all objects
                bpy.context.view_layer.objects.active = ob   # make the current object the active object 
                ob.select_set(True)                          # select the object
                print(obj.name, ": Selected Successfully")
                
                
                modBendName = "SimpleDeform_Bend"
                
                for modifier in obj.modifiers:
                    if modifier.name == modBendName:
                        obj.modifiers.remove(obj.modifiers.get(modBendName))
                        print(obj.name, ": DELETED existing", modBendName)
                        
                modBend = obj.modifiers.new(name= modBendName, type='SIMPLE_DEFORM') # add simple Deform to mesh
                modBend.deform_method = 'BEND'                                       # change deform to bend
                modBend.angle = math.radians(bend_angle)                             # set initial angle before adding animated noise
                modBend.keyframe_insert("angle",frame=0)                             # add key at frame 0
                fNoise = bpy.ops.graph.fmodifier_add(type='NOISE')
                

                print(obj.name, ": Added", modBendName)

Error Message

    File "C:\Program Files\Blender Foundation\Blender 4.1\4.1\scripts\modules\bpy\ops.py", line 109, in __call__
        ret = _op_call(self.idname_py(), kw)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    RuntimeError: Operator bpy.ops.graph.fmodifier_add.poll() failed, context is incorrect

$\endgroup$

2 Answers 2

2
$\begingroup$

This bpy.ops needs to be run in a specific editor area, so bpy.ops.graph.fmodifier_add fail without change to Graph Editor

Add Noise modifier on fcurve

import bpy

def get_fcs_set(ob):
    if hasattr(ob, "animation_data"):
        animation_data = ob.animation_data
        if hasattr(animation_data, "action"):
            action = animation_data.action
            if hasattr(action, "fcurves"):
                return set(action.fcurves)
    return set()

ob = bpy.context.object
old_fcs = get_fcs_set(ob)
success = bpy.context.object.keyframe_insert("location", index=0)
if success:
    new_fcs_added = get_fcs_set(ob) - old_fcs
    fc = list(new_fcs_added)[0]
    fmd = fc.modifiers.new("NOISE")
$\endgroup$
4
  • $\begingroup$ Thank you for answering! I tried incorporating your code into mine but I got an error say: ``` IndexError: list index out of range ``` The error was for fc = list(new_fcs_added)[0] $\endgroup$
    – ekelly
    Commented Jul 29 at 20:50
  • $\begingroup$ Have you put old_fcs = get_fcs_set(ob) before keyframe_insert()? You can show me the new code to reproduce the issue. $\endgroup$
    – X Y
    Commented Jul 30 at 2:43
  • $\begingroup$ Thank you! It won't let me add all the code here so I'll type it as an answer. I really appreciate it! $\endgroup$
    – ekelly
    Commented Jul 30 at 16:35
  • $\begingroup$ Actually, I was able to get it working. I'll post what I did. Thank you so much for all your help. I was spinning my wheels trying to figure it out. $\endgroup$
    – ekelly
    Commented Jul 30 at 19:10
0
$\begingroup$

@X Y Here is how I was able to incorporate your code into what I had. I hope you have a wonderful rest of your day!

def get_fcurves_set(ob):
    if hasattr(ob, "animation_data"):
        animation_data = ob.animation_data
        if hasattr(animation_data, "action"):
            action = animation_data.action
            if hasattr(action, "fcurves"):
                return set(action.fcurves)
    return set()
        
def anim_bend(input_name, bend_angle):
        
        obj = bpy.context.active_object
        
        # for each selected object, run this
        for obj in bpy.data.objects:
            if input_name in obj.name:
                
                #select objects individually 
                ob = bpy.context.scene.objects[obj.name]     # get the object
                bpy.ops.object.select_all(action='DESELECT') # deselect all objects
                bpy.context.view_layer.objects.active = ob   # make the cube the active object 
                ob.select_set(True)                          # select the object
                print(obj.name, ": Selected Successfully")
                
                
                
                #ADD SIMPLE DEFORM (BEND)
                modBendName = "SimpleDeform_Bend"
                
                #delete existing bend modifiers with the same name as modBendName
                for modifier in obj.modifiers:
                    if modifier.name == modBendName:
                        obj.modifiers.remove(obj.modifiers.get(modBendName))
                        print(obj.name, ": DELETED existing", modBendName)
                        
                modBend = obj.modifiers.new(name= modBendName, type='SIMPLE_DEFORM') # add simple Deform to mesh
                modBend.deform_method = 'BEND'                                       # change deform to bend
                modBend.angle = math.radians(bend_angle)                             # set initial angle before adding animated noise
                
                
                
                fmodName = "Noise_Angle"
                
                ob = bpy.context.object
                old_fcurves = get_fcurves_set(obj.name)
                success = modBend.keyframe_insert("angle",frame=0)
                
                if success:
                    new_fcurves_added = get_fcurves_set(ob) - old_fcurves
                    fc = list(new_fcurves_added)[0]
                    
                    #delete existing fcurve modifiers with the same name as fmodName
                    for mod in fc.modifiers:
                        if mod.name == fmodName:
                            print(fmodName)
                            fc_modifier_to_remove = fc.modifiers.get(fmodName)
                            fc.modifiers.remove(fc_modifier_to_remove)
                            print(obj.name, ": DELETED existing Fcurve Modifier", fmodName)
                    fmd = fc.modifiers.new("NOISE")
                    fmd.name = fmodName
                    fmd.scale = 0.1
                    
                

                        
                print(obj.name, ": Added", modBendName)
               
$\endgroup$

You must log in to answer this question.

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