FBX: Enable the Collection exporter feature

This enables FBX to be used as a Collection exporter[0].

To enable this, two changes were made:
- The `export_scene.fbx` operator was configured on the File Handler
- A `collection` property was added to the export Operator

This `collection` property is akin to the special `filepath` and
`directory` properties in that this is how Blender will communicate with
the addon.

Because FBX already has a `use_active_collection` property, a small
layout change is included to not draw this property when used as a
Collection exporter as that would introduce confusion. It also makes
sense to only draw `use_selection` and `use_visible` while in the file
browser in the same way. Feedback was received about this during
development and indeed these toggles will be skipped during processing
anyhow.

An additional discussion point to consider is if we want this new
`collection` property drawn when using `File`->`Export` to allow the
user to control which exact collection to export as opposed to just the
"Active Collection". This isn't included in the patch currently.

[0] To test, go to `Collection Properties` -> `Exporters` -> `Add` and
select FBX after applying this patch.

Pull Request: https://projects.blender.org/blender/blender-addons/pulls/105273
This commit is contained in:
Jesse Yurkovich
2024-04-16 05:13:33 +02:00
committed by Jesse Yurkovich
parent 84814b8270
commit 4f815e960a
2 changed files with 38 additions and 16 deletions

View File

@ -315,6 +315,11 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
description="Export only objects from the active collection (and its children)",
default=False,
)
collection: StringProperty(
name="Source Collection",
description="Export only objects from this collection (and its children)",
default="",
)
global_scale: FloatProperty(
name="Scale",
description="Scale all data (Some importers do not support scaled armatures!)",
@ -557,8 +562,11 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
export_main(layout, self)
export_panel_include(layout, self)
# Are we inside the File browser
is_file_browser = context.space_data.type == 'FILE_BROWSER'
export_main(layout, self, is_file_browser)
export_panel_include(layout, self, is_file_browser)
export_panel_transform(layout, self)
export_panel_geometry(layout, self)
export_panel_armature(layout, self)
@ -589,27 +597,29 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
return export_fbx_bin.save(self, context, **keywords)
def export_main(layout, operator):
def export_main(layout, operator, is_file_browser):
row = layout.row(align=True)
row.prop(operator, "path_mode")
sub = row.row(align=True)
sub.enabled = (operator.path_mode == 'COPY')
sub.prop(operator, "embed_textures", text="", icon='PACKAGE' if operator.embed_textures else 'UGLYPACKAGE')
row = layout.row(align=True)
row.prop(operator, "batch_mode")
sub = row.row(align=True)
sub.prop(operator, "use_batch_own_dir", text="", icon='NEWFOLDER')
if is_file_browser:
row = layout.row(align=True)
row.prop(operator, "batch_mode")
sub = row.row(align=True)
sub.prop(operator, "use_batch_own_dir", text="", icon='NEWFOLDER')
def export_panel_include(layout, operator):
def export_panel_include(layout, operator, is_file_browser):
header, body = layout.panel("FBX_export_include", default_closed=False)
header.label(text="Include")
if body:
sublayout = body.column(heading="Limit to")
sublayout.enabled = (operator.batch_mode == 'OFF')
sublayout.prop(operator, "use_selection")
sublayout.prop(operator, "use_visible")
sublayout.prop(operator, "use_active_collection")
if is_file_browser:
sublayout.prop(operator, "use_selection")
sublayout.prop(operator, "use_visible")
sublayout.prop(operator, "use_active_collection")
body.column().prop(operator, "object_types")
body.prop(operator, "use_custom_props")
@ -681,6 +691,7 @@ class IO_FH_fbx(bpy.types.FileHandler):
bl_idname = "IO_FH_fbx"
bl_label = "FBX"
bl_import_operator = "import_scene.fbx"
bl_export_operator = "export_scene.fbx"
bl_file_extensions = ".fbx"
@classmethod

View File

@ -3586,6 +3586,7 @@ def save(operator, context,
use_selection=False,
use_visible=False,
use_active_collection=False,
collection="",
batch_mode='OFF',
use_batch_own_dir=False,
**kwargs
@ -3606,13 +3607,23 @@ def save(operator, context,
if batch_mode == 'OFF':
kwargs_mod = kwargs.copy()
source_collection = None
if use_active_collection:
if use_selection:
ctx_objects = tuple(obj
for obj in context.view_layer.active_layer_collection.collection.all_objects
if obj.select_get())
source_collection = context.view_layer.active_layer_collection.collection
elif collection:
local_collection = bpy.data.collections.get((collection, None))
if local_collection:
source_collection = local_collection
else:
ctx_objects = context.view_layer.active_layer_collection.collection.all_objects
operator.report({'ERROR'}, "Collection '%s' was not found" % collection)
return {'CANCELLED'}
if source_collection:
if use_selection:
ctx_objects = tuple(obj for obj in source_collection.all_objects if obj.select_get())
else:
ctx_objects = source_collection.all_objects
else:
if use_selection:
ctx_objects = context.selected_objects