I have a script that goes through all of the actions in bpy.data.actions. for action in bpy.data.actions:
First, is there a way to return the object the action is associated with and second, is there a way to return whether or not that object is selected?
Any help is greatly appreciated!
1 Answer
Make a lookup table.
In going the other way can look at all objects in blend and from their animation data check all actions either assigned directly or via the NLA.
For example sake have used a defaultdict
assigned to a set. Iterated over all objects and added all assoc. actions to set.
import bpy
from collections import defaultdict
actions = defaultdict(set)
for ob in bpy.data.objects:
if not ob.animation_data:
continue
ad = ob.animation_data
if ad.action:
actions[ob.name].add(ad.action)
actions[ob.name].update(s.action for t in ad.nla_tracks for s in t.strips if s.action)
# print results
for k, v in actions.items():
print(k, v)
Example output
Cube {bpy.data.actions['Action'], bpy.data.actions['CubeAction.002'], bpy.data.actions['CubeAction']}
Once we have created lookup above can iterate over actions where any that intersect actions[ob.name]
are associated with object ob
An object is selected if ob.select_set()
is True
Alter above and use for ob in context.selected_objects:
to only look at actions assigned to selected objects in the context scene. (context = bpy.context
If we make test code using context
it pastes nicely into operator / panel code)
When an action is created by keyframing in the UI the action is assigned name, for example on object "Cube", "CubeAction" and the action is given an Action.id_root = 'OBJECT'
to associate this action with objects (not meshes, shapekeys etc).
However IMO perhaps neither can be relied on, if the action is renamed, or created via code and the id_root
is not set.