Try this updated code:
bl_info = {
"name" : "MyTab",
"author" : "Mary Kita",
"version" :(0, 1),
"blender" : (2, 93, 0),
"location":"View3D > Tool",
"description": "here your addon description",
"doc_url": "",
"tracker_url": "",
"category": "Custom"
}
import bpy
from bpy.types import Operator, PropertyGroup, Panel
# Recursivly transverse layer_collection for a particular name
def recurLayerCollection(layerColl, collName):
found = None
if (layerColl.name == collName):
return layerColl
for layer in layerColl.children:
found = recurLayerCollection(layer, collName)
if found:
return found
class MYPANEL_PT_panel(Panel):
bl_label = "MyPanel"
# bl_idname = "my_panel" #id name du premier panneau
bl_space_type = 'VIEW_3D' # le type d'espace c'est à dire espace 3D
bl_region_type = 'UI' # ca agit sur quoi ? sur l'UI
bl_category = 'MyTab' # nom de l'outil qui sera affiché sur les onglets tools
def draw(self, context):
mypanel_props = context.scene.MYPANEL_PG_props
layout = self.layout
row = layout.row()
row.prop(mypanel_props, "my_checkbox")
row = layout.row()
row.prop(mypanel_props, "my_folder")
row = layout.row()
row.operator("fbx.exporter",text="Export")
class MYPANEL_OT_operator(Operator):
# export in a Substance Folder for Stone project # Use this as a tooltip for menu items and buttons.
bl_idname = "fbx.exporter" # Unique identifier for buttons and menu items to reference.
bl_label = "fbx_exporter" # Display name in the interface.
bl_options = {'REGISTER', 'UNDO'} # Enable undo for the operator.
def execute(self, context): # execute() is called when running the operator.
mypanel_props = context.scene.MYPANEL_PG_props
# Get the selected objects
selectedObject = context.selected_objects
# Get the active object
activeObject = context.view_layer.objects.active
# Get the name of selected object
for obj in selectedObject:
# to define folderPath
# rajouter trjs \\ pour définir un chemin
folderPath = mypanel_props.my_folder
if mypanel_props.my_checkbox == True:
#Switching active Collection to active Object selected
ucol = context.object.users_collection
for i in ucol:
layer_collection = bpy.context.view_layer.layer_collection
layerColl = recurLayerCollection(layer_collection, i.name)
bpy.context.view_layer.active_layer_collection = layerColl
fileNameCol = bpy.context.collection.name + '_collection.fbx'
# customfilePath will be used to filepath of FPX API operator
customFilePath = folderPath + fileNameCol
# FBX API operator
bpy.ops.export_scene.fbx(
filepath= customFilePath,
check_existing=True,
filter_glob='*.fbx',
use_selection=True,
use_active_collection=False,
global_scale=1.0,
apply_unit_scale=True,
apply_scale_options='FBX_SCALE_UNITS',
bake_space_transform=False,
object_types={'ARMATURE', 'CAMERA', 'EMPTY', 'LIGHT', 'MESH', 'OTHER'},
use_mesh_modifiers=True,
use_mesh_modifiers_render=True,
mesh_smooth_type='OFF',
use_subsurf=False,
use_mesh_edges=False,
use_tspace=False,
use_custom_props=False,
add_leaf_bones=True,
primary_bone_axis='Y',
secondary_bone_axis='X',
use_armature_deform_only=False,
armature_nodetype='NULL',
bake_anim=True,
bake_anim_use_all_bones=True,
bake_anim_use_nla_strips=True,
bake_anim_use_all_actions=True,
bake_anim_force_startend_keying=True,
bake_anim_step=1.0,
bake_anim_simplify_factor=1.0,
path_mode='AUTO',
embed_textures=False,
batch_mode='OFF',
use_batch_own_dir=True,
use_metadata=True,
axis_forward='-Z',
axis_up='Y'
)
if mypanel_props.my_checkbox == False:
# deselecting all and make each previously selected objects by one selected and active
bpy.ops.object.select_all(action='DESELECT')
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
fileNameObj = bpy.context.active_object.name + '.fbx'
# customfilePath will be used to filepath of FPX API operator
customFilePath = folderPath + fileNameObj
# FBX API operator
bpy.ops.export_scene.fbx(
filepath= customFilePath,
check_existing=True,
filter_glob='*.fbx',
use_selection=True,
use_active_collection=False,
global_scale=1.0,
apply_unit_scale=True,
apply_scale_options='FBX_SCALE_UNITS',
bake_space_transform=False,
object_types={'ARMATURE', 'CAMERA', 'EMPTY', 'LIGHT', 'MESH', 'OTHER'},
use_mesh_modifiers=True,
use_mesh_modifiers_render=True,
mesh_smooth_type='OFF',
use_subsurf=False,
use_mesh_edges=False,
use_tspace=False,
use_custom_props=False,
add_leaf_bones=True,
primary_bone_axis='Y',
secondary_bone_axis='X',
use_armature_deform_only=False,
armature_nodetype='NULL',
bake_anim=True,
bake_anim_use_all_bones=True,
bake_anim_use_nla_strips=True,
bake_anim_use_all_actions=True,
bake_anim_force_startend_keying=True,
bake_anim_step=1.0,
bake_anim_simplify_factor=1.0,
path_mode='AUTO',
embed_textures=False,
batch_mode='OFF',
use_batch_own_dir=True,
use_metadata=True,
axis_forward='-Z',
axis_up='Y'
)
# restoring original selection
for obj in selectedObject:
obj.select_set(True)
# restoring original active object
bpy.context.view_layer.objects.active = activeObject
# Lets Blender know the operator finished successfully.
return {'FINISHED'}
class MYPANEL_PG_props(PropertyGroup):
my_checkbox: bpy.props.BoolProperty(
name="is Collection",
description="is Collection ?",
default = False
)
my_folder: bpy.props.StringProperty(
name = "Path",
description = "Path to the folder containing the files to import",
default = "C:\\Users\\MaryKita\\Desktop\\FbxFolder\\",
subtype = 'DIR_PATH'
)
classes = (
MYPANEL_PT_panel,
MYPANEL_OT_operator,
MYPANEL_PG_props,
)
register, unregister = bpy.utils.register_classes_factory(classes)
def register():
for c in classes:
bpy.utils.register_class(c)
bpy.types.Scene.MYPANEL_PG_props = bpy.props.PointerProperty(type = MYPANEL_PG_props)
def unregister():
for c in classes:
bpy.utils.unregister_class(c)
del bpy.types.Scene.MYPANEL_PG_props
if __name__ == "__main__":
register()
Note:
- if “is Collection” not active, it creates *.fbx file for each object selected.
- if “is Collection” is active, it creates *_collection.fbx file for selected objects and name it with collection name where active selected object is located.
- added a “Path” option where you can specify a destination folder.