Skip to content
Snippets Groups Projects
export_fbx_bin.py 145 KiB
Newer Older
  • Learn to ignore specific revisions
  •     # And we are down, we can write the whole thing!
        encode_bin.write(filepath, root, FBX_VERSION)
    
    
        # Clear cached ObjectWrappers!
        ObjectWrapper.cache_clear()
    
    
        # copy all collected files, if we did not embed them.
        if not media_settings.embed_textures:
            bpy_extras.io_utils.path_reference_copy(media_settings.copy_set)
    
        print('export finished in %.4f sec.' % (time.process_time() - start_time))
        return {'FINISHED'}
    
    
    # defaults for applications, currently only unity but could add others.
    def defaults_unity3d():
        return {
    
    Bastien Montagne's avatar
    Bastien Montagne committed
            # These options seem to produce the same result as the old Ascii exporter in Unity3D:
            "version": 'BIN7400',
            "axis_up": 'Y',
            "axis_forward": '-Z',
    
            "global_matrix": Matrix.Rotation(-math.pi / 2.0, 4, 'X'),
    
    Bastien Montagne's avatar
    Bastien Montagne committed
            # Should really be True, but it can cause problems if a model is already in a scene or prefab
            # with the old transforms.
            "bake_space_transform": False,
    
    
            "use_selection": False,
    
    Bastien Montagne's avatar
    Bastien Montagne committed
    
            "object_types": {'ARMATURE', 'EMPTY', 'MESH', 'OTHER'},
    
            "use_mesh_modifiers": True,
    
    Bastien Montagne's avatar
    Bastien Montagne committed
            "use_mesh_edges": False,
            "mesh_smooth_type": 'FACE',
            "use_tspace": False,  # XXX Why? Unity is expected to support tspace import...
    
            "use_armature_deform_only": True,
    
    
            "use_custom_props": True,
    
            "bake_anim": True,
    
    Bastien Montagne's avatar
    Bastien Montagne committed
            "bake_anim_simplify_factor": 1.0,
            "bake_anim_step": 1.0,
            "bake_anim_use_nla_strips": True,
            "bake_anim_use_all_actions": True,
    
            "add_leaf_bones": False,  # Avoid memory/performance cost for something only useful for modelling
            "primary_bone_axis": 'Y',  # Doesn't really matter for Unity, so leave unchanged
            "secondary_bone_axis": 'X',
    
    Bastien Montagne's avatar
    Bastien Montagne committed
    
            "path_mode": 'AUTO',
            "embed_textures": False,
    
            "batch_mode": 'OFF',
        }
    
    
    def save(operator, context,
             filepath="",
             use_selection=False,
             batch_mode='OFF',
             use_batch_own_dir=False,
             **kwargs
             ):
        """
        This is a wrapper around save_single, which handles multi-scenes (or groups) cases, when batch-exporting a whole
        .blend file.
        """
    
        ret = None
    
    
        active_object = context.scene.objects.active
    
    
        if active_object and active_object.mode != 'OBJECT' and bpy.ops.object.mode_set.poll():
            org_mode = active_object.mode
    
            bpy.ops.object.mode_set(mode='OBJECT')
    
        if batch_mode == 'OFF':
            kwargs_mod = kwargs.copy()
            if use_selection:
                kwargs_mod["context_objects"] = context.selected_objects
            else:
                kwargs_mod["context_objects"] = context.scene.objects
    
            ret = save_single(operator, context.scene, filepath, **kwargs_mod)
        else:
            fbxpath = filepath
    
            prefix = os.path.basename(fbxpath)
            if prefix:
                fbxpath = os.path.dirname(fbxpath)
    
            if batch_mode == 'GROUP':
    
                data_seq = tuple(grp for grp in bpy.data.groups if grp.objects)
    
            else:
                data_seq = bpy.data.scenes
    
            # call this function within a loop with BATCH_ENABLE == False
            # no scene switching done at the moment.
            # orig_sce = context.scene
    
            new_fbxpath = fbxpath  # own dir option modifies, we need to keep an original
            for data in data_seq:  # scene or group
    
                newname = "_".join((prefix, bpy.path.clean_name(data.name))) if prefix else bpy.path.clean_name(data.name)
    
    
                if use_batch_own_dir:
                    new_fbxpath = os.path.join(fbxpath, newname)
                    # path may already exist
                    # TODO - might exist but be a file. unlikely but should probably account for it.
    
                    if not os.path.exists(new_fbxpath):
                        os.makedirs(new_fbxpath)
    
                filepath = os.path.join(new_fbxpath, newname + '.fbx')
    
                print('\nBatch exporting %s as...\n\t%r' % (data, filepath))
    
                if batch_mode == 'GROUP':  # group
                    # group, so objects update properly, add a dummy scene.
                    scene = bpy.data.scenes.new(name="FBX_Temp")
                    scene.layers = [True] * 20
                    # bpy.data.scenes.active = scene # XXX, cant switch
    
                    src_scenes = {}  # Count how much each 'source' scenes are used.
    
                    for ob_base in data.objects:
    
                        for src_sce in ob_base.users_scene:
                            if src_sce not in src_scenes:
                                src_scenes[src_sce] = 0
                            src_scenes[src_sce] += 1
    
                        scene.objects.link(ob_base)
    
    
                    # Find the 'most used' source scene, and use its unit settings. This is somewhat weak, but should work
                    # fine in most cases, and avoids stupid issues like T41931.
                    best_src_scene = None
                    best_src_scene_users = 0
                    for sce, nbr_users in src_scenes.items():
                        if (nbr_users) > best_src_scene_users:
                            best_src_scene_users = nbr_users
                            best_src_scene = sce
                    scene.unit_settings.system = best_src_scene.unit_settings.system
                    scene.unit_settings.system_rotation = best_src_scene.unit_settings.system_rotation
                    scene.unit_settings.scale_length = best_src_scene.unit_settings.scale_length
    
    
                    scene.update()
                    # TODO - BUMMER! Armatures not in the group wont animate the mesh
                else:
                    scene = data
    
                kwargs_batch = kwargs.copy()
                kwargs_batch["context_objects"] = data.objects
    
                save_single(operator, scene, filepath, **kwargs_batch)
    
                if batch_mode == 'GROUP':
                    # remove temp group scene
                    bpy.data.scenes.remove(scene)
    
            # no active scene changing!
            # bpy.data.scenes.active = orig_sce
    
            ret = {'FINISHED'}  # so the script wont run after we have batch exported.
    
    
        if active_object and org_mode and bpy.ops.object.mode_set.poll():
    
            bpy.ops.object.mode_set(mode=org_mode)
    
        return ret