import bpy import os from bpy.props import (StringProperty, PointerProperty, EnumProperty, BoolProperty) from bpy.types import (Panel, Operator, AddonPreferences, PropertyGroup) bl_info = \ { "name": "Unreal Exporter", "author": "Bozarre", "version": (1, 0, 0), "blender": (4, 2, 0), "location": "View 3D > Object Mode > Unreal Exporter", "description": "Bartch exporter for Unreal Engine", "warning": "", "wiki_url": "", "tracker_url": "", "category": "Exporter", } class UEExporterSettings(PropertyGroup): path : StringProperty( #name="", description="Path to Directory (empty means same as curren file)", default="//", maxlen=1024, subtype='FILE_PATH') source_collection : StringProperty( description="Collection name (collisions don't have to be in the same collection", default="Export", maxlen=1024) collisions: BoolProperty( name="Export Collisions", description="Whether to export the collision shapes", default = True ) local_origin: BoolProperty( name="Export Origin", description="Whether to use the objects origin as the export origin", default = False ) class VIEW3D_PT_PanelExportAll(bpy.types.Panel): bl_label = "Export Selected" bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_category = "UE Exporter" bl_context = "objectmode" def draw(self, context): layout = self.layout scn = context.scene layout.label(text="Export Path Location:") layout.prop(scn.ue_exporter, "path", text="") layout.label(text="Collection to export") layout.prop(scn.ue_exporter, "source_collection", text="") layout.prop(scn.ue_exporter, "local_origin", text=" Export Origin") layout.prop(scn.ue_exporter, "collisions", text=" Export Collisions") layout.operator("ue_exporter_obs.separate_export", text='Export Seperate', icon='TRIA_RIGHT') layout.operator("ue_exporter_obs.combine_export", text='Export Combined', icon='TRIA_RIGHT') class OBJECT_OT_SeparateExport(bpy.types.Operator): bl_idname = "ue_exporter_obs.separate_export" bl_label = "Export Selected" bl_options = {"UNDO"} def execute(self, context): return {'FINISHED'} def invoke(self, context, event): SeparateExport(context.scene.ue_exporter.path) self.report({'INFO'}, 'Exported') return {'FINISHED'} class OBJECT_OT_CombineExport(bpy.types.Operator): bl_idname = "ue_exporter_obs.combine_export" bl_label = "Export Selected" bl_options = {"UNDO"} def execute(self, context): return {'FINISHED'} def invoke(self, context, event): CombineExport(context.scene.ue_exporter.path) self.report({'INFO'}, 'Exported') return {'FINISHED'} def SeparateExport(exportFolder): objects = bpy.data.collections[bpy.context.scene.ue_exporter.source_collection].all_objects #for some absurd logic it works only if objects comes from the selection, no time to explain... for object in objects: object.select_set(True) objects = bpy.context.selected_objects bpy.ops.object.select_all(action='DESELECT') for object in objects: object.select_set(True) if object.type not in ['MESH']: continue exportName = bpy.path.abspath(exportFolder) + object.name + '.fbx' bpy.ops.export_scene.fbx(filepath=exportName, use_selection=True, mesh_smooth_type='FACE') object.select_set(False) def CombineExport(exportFolder): objects = bpy.data.collections[bpy.context.scene.ue_exporter.source_collection].all_objects #for some absurd logic it works only if objects comes from the selection, no time to explain... for object in objects: object.select_set(True) bpy.ops.object.select_all(action='DESELECT') isOrigin = bpy.context.scene.ue_exporter.local_origin origLocs = [] for object in objects: object.select_set(True) if isOrigin: origLocs.append(object.location.copy()) object.location = (0.0,0.0,0.0) object.name = object.name exportName = exportFolder + bpy.context.active_object.name + '.fbx' bpy.ops.export_scene.fbx(filepath=exportName, use_selection=True, mesh_smooth_type='FACE') for object in objects: if isOrigin: object.location = origLocs.pop(0) classes = ( VIEW3D_PT_PanelExportAll, OBJECT_OT_SeparateExport, OBJECT_OT_CombineExport, UEExporterSettings ) def register(): for c in classes: bpy.utils.register_class(c) bpy.types.Scene.ue_exporter = bpy.props.PointerProperty(type=UEExporterSettings) def unregister(): for c in reversed(classes): bpy.utils.unregister_class(c) del bpy.types.Scene.ue_exporter if __name__ == "__main__": register()