Skip to content

Instantly share code, notes, and snippets.

@p2or
Last active May 21, 2023 18:02
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save p2or/a18df7e77d518d0a1a0a411c985a51bc to your computer and use it in GitHub Desktop.
Save p2or/a18df7e77d518d0a1a0a411c985a51bc to your computer and use it in GitHub Desktop.
Blender 2.92+ - Batch import obj files based on my answer here: https://blender.stackexchange.com/a/31825/31447 #Blender #BSE
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
bl_info = {
"name": "Batch Import Wavefront (.obj)",
"author": "p2or",
"version": (0, 1, 0),
"blender": (2, 92, 0),
"location": "File > Import-Export",
"description": "Import multiple OBJ files, UV's, materials",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"category": "Import-Export"}
import bpy
import os
from bpy_extras.io_utils import ImportHelper
from bpy.props import (BoolProperty,
FloatProperty,
StringProperty,
EnumProperty,
CollectionProperty
)
class ImportMultipleObjs(bpy.types.Operator, ImportHelper):
"""Batch Import Wavefront obj"""
bl_idname = "import_scene.multiple_objs"
bl_label = "Import multiple OBJ's"
bl_options = {'PRESET', 'UNDO'}
# ImportHelper mixin class uses this
filename_ext = ".obj"
filter_glob = StringProperty(
default="*.obj",
options={'HIDDEN'},
)
# Selected files
files: CollectionProperty(type=bpy.types.PropertyGroup)
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
edges_setting: BoolProperty(
name="Lines",
description="Import lines and faces with 2 verts as edge",
default=True,
)
smooth_groups_setting: BoolProperty(
name="Smooth Groups",
description="Surround smooth groups by sharp edges",
default=True,
)
split_objects_setting: BoolProperty(
name="Object",
description="Import OBJ Objects into Blender Objects",
default=True,
)
split_groups_setting: BoolProperty(
name="Group",
description="Import OBJ Groups into Blender Objects",
default=True,
)
groups_as_vgroups_setting: BoolProperty(
name="Poly Groups",
description="Import OBJ groups as vertex groups",
default=False,
)
image_search_setting: BoolProperty(
name="Image Search",
description="Search subdirs for any associated images "
"(Warning, may be slow)",
default=True,
)
split_mode_setting: EnumProperty(
name="Split",
items=(('ON', "Split", "Split geometry, omits unused verts"),
('OFF', "Keep Vert Order", "Keep vertex order from file"),
),
)
clamp_size_setting: FloatProperty(
name="Clamp Size",
description="Clamp bounds under this value (zero to disable)",
min=0.0, max=1000.0,
soft_min=0.0, soft_max=1000.0,
default=0.0,
)
axis_forward_setting: EnumProperty(
name="Forward",
items=(('X', "X Forward", ""),
('Y', "Y Forward", ""),
('Z', "Z Forward", ""),
('-X', "-X Forward", ""),
('-Y', "-Y Forward", ""),
('-Z', "-Z Forward", ""),
),
default='-Z',
)
axis_up_setting: EnumProperty(
name="Up",
items=(('X', "X Up", ""),
('Y', "Y Up", ""),
('Z', "Z Up", ""),
('-X', "-X Up", ""),
('-Y', "-Y Up", ""),
('-Z', "-Z Up", ""),
),
default='Y',
)
def draw(self, context):
layout = self.layout
row = layout.row(align=True)
row.prop(self, "smooth_groups_setting")
row.prop(self, "edges_setting")
box = layout.box()
row = box.row()
row.prop(self, "split_mode_setting", expand=True)
row = box.row()
if self.split_mode_setting == 'ON':
row.label(text="Split by:")
row.prop(self, "split_objects_setting")
row.prop(self, "split_groups_setting")
else:
row.prop(self, "groups_as_vgroups_setting")
row = layout.split(factor=0.67)
row.prop(self, "clamp_size_setting")
layout.prop(self, "axis_forward_setting")
layout.prop(self, "axis_up_setting")
layout.prop(self, "image_search_setting")
def execute(self, context):
if not self.filepath:
self.report({'ERROR'}, "Nothing selected.")
return {"CANCELLED"}
# Get the folder and all selected obj files
folder = os.path.dirname(self.filepath)
selected_obj_files = [f for f in self.files if f.name.endswith(".obj")]
if selected_obj_files:
for i in selected_obj_files:
# Generate full path to file
path_to_file = os.path.join(folder, i.name)
# Call obj operator and assign UI values
bpy.ops.import_scene.obj(
filepath = path_to_file,
axis_forward = self.axis_forward_setting,
axis_up = self.axis_up_setting,
use_edges = self.edges_setting,
use_smooth_groups = self.smooth_groups_setting,
use_split_objects = self.split_objects_setting,
use_split_groups = self.split_groups_setting,
use_groups_as_vgroups = self.groups_as_vgroups_setting,
use_image_search = self.image_search_setting,
split_mode = self.split_mode_setting,
global_clamp_size = self.clamp_size_setting
)
else:
self.report({'ERROR'}, "No obj file in selection.")
return {"CANCELLED"}
return {'FINISHED'}
# Only needed if you want to add into a dynamic menu
def menu_func_import(self, context):
self.layout.operator(ImportMultipleObjs.bl_idname, text="Wavefront Batch (.obj)")
def register():
bpy.utils.register_class(ImportMultipleObjs)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
def unregister():
bpy.utils.unregister_class(ImportMultipleObjs)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
if __name__ == "__main__":
register()
# test call
#bpy.ops.import_scene.multiple_objs('INVOKE_DEFAULT')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment