import bpy from bpy.types import LayerCollection, Object, NlaTrack # Enter object mode bpy.ops.object.mode_set(mode='OBJECT') # FIRST, toggle collections collections_exportable = [ "insurrectionist", "infantry", "rigging", "geometry", "grapple", "baton", "helmet", "gun", "jetpack" ] def toggle_collection(coll: LayerCollection): # Iterate over all child LayerCollections for child in coll.children.values(): c: LayerCollection = child # Force include/exclude character-related collections so they're included/excluded from export c.exclude = not (c.name in collections_exportable) if c.name == "insurrectionist" or c.name == "infantry": bpy.context.view_layer.active_layer_collection = c toggle_collection(bpy.context.view_layer.layer_collection) # Find rig to make it active, and select all objects for objBase in bpy.context.scene.objects: obj: Object = objBase if obj.type == 'ARMATURE': bpy.context.view_layer.objects.active = obj if obj.visible_get(): obj.select_set(True) # EXTREMELY UGLY HACK TO EXIT TWEAK MODE # see: https://blender.stackexchange.com/questions/316547/how-to-override-context-area-using-script-when-running-blender-using-command-lin # and https://blender.stackexchange.com/questions/6101/poll-failed-context-incorrect-example-bpy-ops-view3d-background-image-add def get_view_nla(): # Get any window for window_manager in bpy.data.window_managers: for window in window_manager.windows: for area in window.screen.areas: area.type = 'NLA_EDITOR' for region in area.regions: if region.type == 'WINDOW': return dict(window=window, workspace=window.workspace, screen=window.screen, area=area, region=region) raise Exception('NLA context not found.') # Forcibly override context to a window so we can access NLA editor with bpy.context.temp_override(**get_view_nla()): if bpy.context.scene.is_nla_tweakmode: bpy.ops.nla.tweakmode_exit() # Exit tweakmode # Go through all NLA tracks, unstar them and mute them bpy.context.active_object.animation_data.nla_tracks.active = None # Make track inactive for trackBase in bpy.context.active_object.animation_data.nla_tracks: track: NlaTrack = trackBase track.mute = True # Mute all tracks track.is_solo = False # Disable solo view for all tracks # Get export directory path: str = bpy.data.filepath.replace('\\Shelby', '').replace('\\Tommy', '') pathPrefix = max(path.rfind('animations/'), path.rfind('animations\\')) pathStart = pathPrefix + len('animations/') pathEnd = max(path.rfind('/'), path.rfind('\\')) # Figure out who made these animations based on filepath fileIndividual = '' if 'tommy' in path: fileIndividual = 'tommy' elif 'shelby' in path: fileIndividual = 'shelby' elif 'alan' in path: fileIndividual = 'alan' # Build export filepath dirName = path[pathStart:pathEnd] filePath = path[:pathPrefix] + 'export\\' + dirName + '\\anims_' + dirName + '_' + fileIndividual + '.fbx' # RIG MUST BE ACTIVE armature = bpy.context.active_object.data # Set all bone layers, INCLUDING mechanical bones, to be visible for i in range(0, 29): armature.layers[i] = True for i in range(29,32): armature.layers[i] = True # Use BoneJuice to bake down all actions # bpy.ops.bj.anim_bakeall() # Make armature local so we can clear all constraints # bpy.ops.object.mode_set(mode='OBJECT') # bpy.ops.object.make_local(type='SELECT_OBDATA') # Clear all posing and pose constraints bpy.ops.object.mode_set(mode='POSE') # Enter pose mode bpy.ops.pose.select_all(action='SELECT') # bpy.ops.pose.constraints_clear() # Clear all constraints bpy.ops.pose.transforms_clear() # Clear all transforms # Export animations bpy.ops.export_scene.fbx( # I/O filepath = filePath, check_existing = False, path_mode = 'STRIP', batch_mode = 'OFF', use_visible = True, object_types = {'MESH', 'ARMATURE'}, axis_forward = '-Y', axis_up = 'Z', # Mesh Settings use_mesh_modifiers = True, use_mesh_modifiers_render = False, use_triangles = True, colors_type = 'NONE', # Animation use_armature_deform_only = True, add_leaf_bones = True, bake_anim = True, bake_anim_use_all_bones = True, bake_anim_use_nla_strips = False, bake_anim_use_all_actions = True, bake_anim_force_startend_keying = True, bake_anim_simplify_factor = 0.0, ) bpy.ops.pose.transforms_clear() # Clear all transforms bpy.ops.object.mode_set(mode='OBJECT') ## FOR DEBUGGING, see https://blender.stackexchange.com/questions/93728/blender-script-run-print-to-console # exit()