How can I use Python to find out if all the selected objects have an action and do something then? If one or more of the selected objects don't have an action, I'd like to print an info/error message saying that "All the selected objects must have an action.".
It's easy to check if an object has shape keys or materials but Terminal says object of type 'Action' has no len()
if I try to do this:
import bpy
o = bpy.context.object
if o.animation_data.action:
num_of_actions = len( o.animation_data.action )
print( "Number of actions: ", num_of_actions )
This helps a little bit but isn't the answer to my problem.
This is the best I can do (had some help from Jeremy for the logic bricks):
# This adds the logic bricks to objects that allow them to be playable in BGE, but only to the selected objects that have an action. Actionless objects are ignored.
# Credit goes mostly to Jeremy Behreandt
import bpy
frames_to_be_played = 9999
ops=bpy.ops
context=bpy.context
# Cache shortcuts.
ops_mesh = ops.mesh
ops_object = ops.object
ops_logic = ops.logic
scene = context.scene
selected = bpy.context.selected_objects
for obj in selected:
ad = obj.animation_data
if ad:
if ad.action:
bpy.context.scene.objects.active = obj
current_object = context.active_object
# Cache shortcut to cube's game engine.
game_engine = current_object.game
# Add sensor.
ops_logic.sensor_add(type='ALWAYS')
#name='Always')
#object=cube_name)
sensor = game_engine.sensors[-1]
# Add controller.
ops_logic.controller_add(type='LOGIC_AND')
#name='And')
#object=cube_name)
controller = game_engine.controllers[-1]
# Add actuator.
ops_logic.actuator_add(type='ACTION')
#name='Action',
#object=cube_name)
actuator = game_engine.actuators[-1]
# Set actuator action to cube's animation data action.
actuator.action = current_object.animation_data.action
# Play mode options are:
# ['PLAY', 'PINGPONG', 'FLIPPER', 'LOOPSTOP', 'LOOPEND', 'PROPERTY']
# 'PLAY' is the default.
#actuator.play_mode = play_mode
# Set frame end to scene end.
#actuator.frame_end = scene.frame_end
actuator.frame_end = frames_to_be_played
# Link logic together.
sensor.link(controller)
actuator.link(controller)
The above script puts the logic bricks to the objects that have an action and ignores the ones that don't have an action, which is good, but not what I'm after.
The ideal case would be to cancel the whole process if even one of the selected objects is missing an action. And notify about that with a message by using this method, which is this snippet code:
import bpy
class RENDER_OT_test(bpy.types.Operator):
bl_idname = 'render.actionerrormessage'
bl_label = 'actionErrorMessage'
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
self.report({'INFO'}, 'Cancelling... All the selected objects must have an action.')
return {'FINISHED'}
bpy.utils.register_class(RENDER_OT_test) # test call to the newly defined operator bpy.ops.render.actionerrormessage() - try out by running the script and pressing spacebar and typing actionErrorMessage
ad.action
Typically multiple actions for an object are added via the NLA. NLA has a list of tracksad.nla_tracks
each track has strips, a strip has an associated action. $\endgroup$ – batFINGER Sep 5 '18 at 9:57len( bpy.context.object.animation_data.nla_tracks.data.action )
is just as useless. What would be the correct way to do this? $\endgroup$ – Manu Järvinen Sep 5 '18 at 11:56len(ad.nla_tracks)
Fromad.action
: it either has one actionif ad.action is not None
or none. There is no way of telling if other actions not in the animation data "slot" are assoc to the object.. Typically to associate an action with an object the NLA is used. Does your file use NLA to store actions.. if not will be of little use? $\endgroup$ – batFINGER Sep 5 '18 at 12:20