I’m using @batFinger’s method for finding the fCurves visible in the Graph Editor. His technique uses bpy.ops.graph.select_all(action='INVERT') to collect visible fCurves in to an array. It works great.
However, if you use a filter or alter visibility of the fCurves so that no fCurves are visible in the graph editor, select_all’s poll will fail and you get an incorrect context error.
Then I noticed that when no fCurves are visible all the selection methods in the Graph’s menu become disabled/grayed out.
Calling any of these operators through script with no fCurves visible will throw a context error, but calling them through their default hotkey does not throw an error.
So what I’m trying to figure out is an if statement or something to test for whatever condition disables the entries in the Select menu so my script can handle/avoid this error the same way calling the operator straight from the keymap avoids it.
Every operator has a .poll() function to return whether or not it can run in the first place.
If the poll returns False, the operator’s button will be unclickable. If it’s false and is executed anyway (via python), it will return an error.
Well, I don’t know if it is 100% true that every operator has a poll() function but I’ve never seen one in Blender’s console without it (I think i’ve seen an addon’s operator class without poll function but i didn’t bother digging into this matter).
what you do is:
if bpy.ops.graph.select_all.poll():
bpy.ops.graph.select_all(action='INVERT')
else:
... # whatever you want to do if it can't run
You could also use try/except, which is the absolute thing to do to always avoid an error
Now, I don't know what you're trying to do but I use a custom search to find which curves are visible
def get_curves(event=None):
context = bpy.context
area = None
## Get the animation editor window's data settings
if event:
# event is checking for the event from an invoke operator, to find the mouse's location, to get the active area
for a in context.screen.areas:
if (event.mouse_x in range(a.x, a.x + a.width) and event.mouse_y in range(a.y, a.y+a.height)):
area = a
try: # if area:
dopesheet = area.spaces[0].dopesheet
only_selected = dopesheet.show_only_selected
show_hidden = dopesheet.show_hidden
show_missing_nla = dopesheet.show_missing_nla
except: # elif "I don't know how this function was run, so just guess the options":
only_selected = False
show_hidden = False
show_missing_nla = False
for obj in context.scene.objects:
anim = obj.animation_data
if anim is None:
continue
if only_selected:
if not obj.select:
continue
if not show_hidden:
if obj.hide:
continue
elif hasattr(context.scene, 'layers'):
# Did not make a version for 2.8 Collections
on_layer = False
for i in range(20):
if context.scene.layers[i] and obj.layers[i]:
on_layer = True
break
if not on_layer:
continue
... # Whatever object reaches this point, their curves are visible in the window.
... # Now you can use curve-by-curve based checks, such as mute/hidden/etc