FBX: Enable the Collection exporter feature #105273

Merged
Jesse Yurkovich merged 6 commits from deadpin/blender-addons:fbx-collectionexport into main 2024-04-16 05:13:36 +02:00
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)", description="Export only objects from the active collection (and its children)",
default=False, default=False,
) )
collection: StringProperty(
name="Source Collection",
description="Export only objects from this collection (and its children)",
default="",
)
global_scale: FloatProperty( global_scale: FloatProperty(
name="Scale", name="Scale",
description="Scale all data (Some importers do not support scaled armatures!)", 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_split = True
layout.use_property_decorate = False # No animation. layout.use_property_decorate = False # No animation.
export_main(layout, self) # Are we inside the File browser
export_panel_include(layout, self) is_file_browser = context.space_data.type == 'FILE_BROWSER'
export_main(layout, self, is_file_browser)
deadpin marked this conversation as resolved Outdated

The batch_mode and use_batch_own_dir properties drawn in export_main() should also only be drawn when is_file_browser because the new code in export_fbx_bin.py is only run when batch_mode == 'OFF' (the default value).

Changing the batch_mode to anything else I don't think makes sense for a Collection exporter.

The `batch_mode` and `use_batch_own_dir` properties drawn in `export_main()` should also only be drawn when `is_file_browser` because the new code in `export_fbx_bin.py` is only run when `batch_mode == 'OFF'` (the default value). Changing the `batch_mode` to anything else I don't think makes sense for a Collection exporter.
export_panel_include(layout, self, is_file_browser)
export_panel_transform(layout, self) export_panel_transform(layout, self)
export_panel_geometry(layout, self) export_panel_geometry(layout, self)
export_panel_armature(layout, self) export_panel_armature(layout, self)
@ -589,24 +597,26 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
return export_fbx_bin.save(self, context, **keywords) 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 = layout.row(align=True)
row.prop(operator, "path_mode") row.prop(operator, "path_mode")
sub = row.row(align=True) sub = row.row(align=True)
sub.enabled = (operator.path_mode == 'COPY') sub.enabled = (operator.path_mode == 'COPY')
sub.prop(operator, "embed_textures", text="", icon='PACKAGE' if operator.embed_textures else 'UGLYPACKAGE') sub.prop(operator, "embed_textures", text="", icon='PACKAGE' if operator.embed_textures else 'UGLYPACKAGE')
if is_file_browser:
row = layout.row(align=True) row = layout.row(align=True)
row.prop(operator, "batch_mode") row.prop(operator, "batch_mode")
sub = row.row(align=True) sub = row.row(align=True)
sub.prop(operator, "use_batch_own_dir", text="", icon='NEWFOLDER') 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, body = layout.panel("FBX_export_include", default_closed=False)
header.label(text="Include") header.label(text="Include")
if body: if body:
sublayout = body.column(heading="Limit to") sublayout = body.column(heading="Limit to")
sublayout.enabled = (operator.batch_mode == 'OFF') sublayout.enabled = (operator.batch_mode == 'OFF')
if is_file_browser:
sublayout.prop(operator, "use_selection") sublayout.prop(operator, "use_selection")
sublayout.prop(operator, "use_visible") sublayout.prop(operator, "use_visible")
sublayout.prop(operator, "use_active_collection") sublayout.prop(operator, "use_active_collection")
@ -681,6 +691,7 @@ class IO_FH_fbx(bpy.types.FileHandler):
bl_idname = "IO_FH_fbx" bl_idname = "IO_FH_fbx"
bl_label = "FBX" bl_label = "FBX"
bl_import_operator = "import_scene.fbx" bl_import_operator = "import_scene.fbx"
bl_export_operator = "export_scene.fbx"
bl_file_extensions = ".fbx" bl_file_extensions = ".fbx"
@classmethod @classmethod

View File

@ -3586,6 +3586,7 @@ def save(operator, context,
use_selection=False, use_selection=False,
use_visible=False, use_visible=False,
use_active_collection=False, use_active_collection=False,
collection="",
batch_mode='OFF', batch_mode='OFF',
use_batch_own_dir=False, use_batch_own_dir=False,
**kwargs **kwargs
@ -3606,13 +3607,23 @@ def save(operator, context,
if batch_mode == 'OFF': if batch_mode == 'OFF':
kwargs_mod = kwargs.copy() kwargs_mod = kwargs.copy()
source_collection = None
if use_active_collection: if use_active_collection:
if use_selection: source_collection = context.view_layer.active_layer_collection.collection
ctx_objects = tuple(obj elif collection:
for obj in context.view_layer.active_layer_collection.collection.all_objects local_collection = bpy.data.collections.get((collection, None))
if obj.select_get()) if local_collection:

Might want to consider whether performing a Collection export from a Collection linked from another file should be supported because a linked Collection can have the same name as a Collection local to the current file (or presumably another Collection linked from another different file).

Currently, exporting from a linked Collection appears to work, but doesn't seem too useful because the Collection's children, export settings and export file path cannot be changed due to being linked from another file.

I don't know if there is a guarantee that bpy.data.collections[collection] will always return a Collection from the current file in preference to a linked Collection with the same name, but it seems like that might be the case from a quick test using the Python Console. So, exporting from a linked Collection with the same name as a local Collection would export the local Collection instead.

If exporting from a linked Collection should not be supported, bpy.data.collections[(collection, None)] can be used to only get a Collection local to the current file.

Otherwise, to get specific Collections, which could have the same name, linked from different libraries would require bpy.data.collections[(collection, library_filepath)] where library_filepath is the value of my_collection.library.filepath or None (when my_collection.library is None due to the Collection being local to the current file).

I don't know enough about how library linked data-blocks are used and supported by different parts of Blender to say if any changes are needed here.

Might want to consider whether performing a Collection export from a Collection linked from another file should be supported because a linked Collection can have the same name as a Collection local to the current file (or presumably another Collection linked from another different file). Currently, exporting from a linked Collection appears to work, but doesn't seem too useful because the Collection's children, export settings and export file path cannot be changed due to being linked from another file. I don't know if there is a guarantee that `bpy.data.collections[collection]` will always return a Collection from the current file in preference to a linked Collection with the same name, but it seems like that might be the case from a quick test using the Python Console. So, exporting from a linked Collection with the same name as a local Collection would export the local Collection instead. If exporting from a linked Collection should not be supported, `bpy.data.collections[(collection, None)]` can be used to only get a Collection local to the current file. Otherwise, to get specific Collections, which could have the same name, linked from different libraries would require `bpy.data.collections[(collection, library_filepath)]` where `library_filepath` is the value of `my_collection.library.filepath` or `None` (when `my_collection.library is None` due to the Collection being local to the current file). I don't know enough about how library linked data-blocks are used and supported by different parts of Blender to say if any changes are needed here.

Currently, exporting from a linked Collection appears to work, but doesn't seem too useful because the Collection's children, export settings and export file path cannot be changed due to being linked from another file.

Hmm, how did you arrive in this state? If you link in a Collection from foo.blend which has an exporter set you shouldn't see anything in the UI as it's not intended to be exportable in the current file. Are you seeing otherwise?

I don't know if there is a guarantee that bpy.data.collections[collection] will always return a Collection from the current file in preference to a linked Collection with the same name, but it seems like that might be the case from a quick test using the Python Console. So, exporting from a linked Collection with the same name as a local Collection would export the local Collection instead.
If exporting from a linked Collection should not be supported, bpy.data.collections[(collection, None)] can be used to only get a Collection local to the current file.

I'll make the change to use the None argument to make it more explicit.

> Currently, exporting from a linked Collection appears to work, but doesn't seem too useful because the Collection's children, export settings and export file path cannot be changed due to being linked from another file. Hmm, how did you arrive in this state? If you link in a Collection from foo.blend which has an exporter set you shouldn't see anything in the UI as it's not intended to be exportable in the current file. Are you seeing otherwise? > I don't know if there is a guarantee that `bpy.data.collections[collection]` will always return a Collection from the current file in preference to a linked Collection with the same name, but it seems like that might be the case from a quick test using the Python Console. So, exporting from a linked Collection with the same name as a local Collection would export the local Collection instead. > If exporting from a linked Collection should not be supported, `bpy.data.collections[(collection, None)]` can be used to only get a Collection local to the current file. I'll make the change to use the `None` argument to make it more explicit.
source_collection = local_collection
else: 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: else:
if use_selection: if use_selection:
ctx_objects = context.selected_objects ctx_objects = context.selected_objects