top of page

Bulk Import - SketchUp .OBJ to Blender

The SketchUp .dae Importer is a Blender add-on designed for batch importing .dae files exported from SketchUp, organizing them into collections, and cleaning up unnecessary objects. It streamlines workflows by automatically joining geometry, moving extras like curves and empties into separate collections, and eliminating imported cameras.

Bulk Import - SketchUp .OBJ to Blender

Broken button... I'll fix it eventually...

bl_info = {

    "name": "SketchUp OBJ Importer",

    "author": "Spencer Clem & ChatGPT",

    "version": (3, 0),

    "blender": (5, 0, 0),

    "location": "View3D > Sidebar > SketchUp Import",

    "description": "Import SketchUp OBJ files as single objects with organized extras.",

    "category": "Import-Export",

}


import bpy

import os

from bpy.props import StringProperty, PointerProperty

from bpy.types import Operator, Panel, PropertyGroup



class SketchUpOBJImportProperties(PropertyGroup):

    obj_directory: StringProperty(

        name="OBJ Directory",

        description="Directory containing the .obj files",

        default="",

        subtype="DIR_PATH",

    )



class SketchUpOBJImportOperator(Operator):

    bl_idname = "import.sketchup_obj_import"

    bl_label = "Import .obj Files"

    bl_description = "Import and process SketchUp .obj files as single objects"

    bl_options = {"REGISTER", "UNDO"}


    def execute(self, context):

        props = context.scene.sketchup_obj_import_props

        obj_directory = bpy.path.abspath(props.obj_directory)


        if not os.path.isdir(obj_directory):

            self.report({"ERROR"}, "Invalid directory path")

            return {"CANCELLED"}


        obj_files = [f for f in os.listdir(obj_directory) if f.lower().endswith(".obj")]

        if not obj_files:

            self.report({"WARNING"}, "No .obj files found in the directory")

            return {"CANCELLED"}


        main_collection = self.ensure_collection("SketchUp Importer")

        extras_collection = self.ensure_collection("Extras", parent_collection=main_collection)


        # Ensure Object mode

        if bpy.context.mode != "OBJECT":

            try:

                bpy.ops.object.mode_set(mode="OBJECT")

            except Exception:

                pass


        for obj_file in obj_files:

            file_path = os.path.join(obj_directory, obj_file)


            before = set(bpy.data.objects)


            # New OBJ importer in Blender 4+ lives under wm

            try:

                bpy.ops.wm.obj_import(filepath=file_path)

            except AttributeError:

                # Fall back to legacy operator name if present

                try:

                    bpy.ops.import_scene.obj(filepath=file_path)

                except Exception as e:

                    self.report({"ERROR"}, f"OBJ import failed for {obj_file}: {e}")

                    return {"CANCELLED"}

            except Exception as e:

                self.report({"ERROR"}, f"OBJ import failed for {obj_file}: {e}")

                return {"CANCELLED"}


            imported = [o for o in bpy.data.objects if o not in before]


            remaining = []

            bpy.ops.object.select_all(action="DESELECT")


            for o in imported:

                if o.name not in bpy.context.view_layer.objects:

                    continue


                if o.type == "CAMERA":

                    bpy.data.objects.remove(o, do_unlink=True)

                elif o.type in {"CURVE", "EMPTY"}:

                    self.unlink_from_other_collections(o)

                    extras_collection.objects.link(o)

                else:

                    remaining.append(o)


            if remaining:

                bpy.ops.object.select_all(action="DESELECT")

                for o in remaining:

                    o.select_set(True)

                bpy.context.view_layer.objects.active = remaining[0]

                bpy.ops.object.join()


                joined = bpy.context.view_layer.objects.active

                joined.name = os.path.splitext(obj_file)[0]


                self.unlink_from_other_collections(joined)

                main_collection.objects.link(joined)


        self.report({"INFO"}, "All .obj files processed successfully!")

        return {"FINISHED"}


    @staticmethod

    def ensure_collection(name, parent_collection=None):

        if name not in bpy.data.collections:

            col = bpy.data.collections.new(name)

            if parent_collection:

                parent_collection.children.link(col)

            else:

                bpy.context.scene.collection.children.link(col)

            return col

        return bpy.data.collections[name]


    @staticmethod

    def unlink_from_other_collections(obj):

        for coll in list(obj.users_collection):

            coll.objects.unlink(obj)



class SketchUpOBJImportPanel(Panel):

    bl_idname = "VIEW3D_PT_sketchup_obj_import"

    bl_label = "SketchUp OBJ Importer"

    bl_space_type = "VIEW_3D"

    bl_region_type = "UI"

    bl_category = "SketchUp Import"


    def draw(self, context):

        layout = self.layout

        props = context.scene.sketchup_obj_import_props


        layout.prop(props, "obj_directory")


        box = layout.box()

        box.label(text="Intended Use:", icon="INFO")

        box.label(text="Use with a SketchUp Ruby script that")

        box.label(text="exports each tag as a separate .obj file.")


        box = layout.box()

        box.label(text="How to Use:", icon="INFO")

        box.label(text="1. Choose the folder with .obj files.")

        box.label(text="2. Click 'Import .obj Files'.")

        box.label(text="3. Each file becomes a single mesh.")

        box.label(text="4. Cameras are deleted.")

        box.label(text="5. Curves/empties move to 'Extras'.")

        box.label(text="6. Everything is under 'SketchUp Importer'.")


        layout.operator("import.sketchup_obj_import", text="Import .obj Files")


        layout.separator()

        layout.label(text="More scripts and tools:")

        layout.label(text="https://www.spencerclem.com/blog-posts-scripts", icon="URL")



classes = [SketchUpOBJImportProperties, SketchUpOBJImportOperator, SketchUpOBJImportPanel]



def register():

    for cls in classes:

        bpy.utils.register_class(cls)

    bpy.types.Scene.sketchup_obj_import_props = PointerProperty(type=SketchUpOBJImportProperties)



def unregister():

    for cls in classes:

        bpy.utils.unregister_class(cls)

    del bpy.types.Scene.sketchup_obj_import_props



if __name__ == "__main__":

    register()


Description

The SketchUp .dae Importer is a powerful add-on for Blender users working with .dae (Collada) files exported from SketchUp. It is specifically designed to complement a SketchUp Ruby export script that exports each tag as its own .dae file, enabling efficient batch import into Blender for further processing.

Key Features:

  1. Batch Import:The add-on allows users to select a folder containing multiple .dae files and import them all at once, eliminating the need for repetitive manual imports.

  2. Object Consolidation:For each .dae file, all geometry is automatically joined into a single object. This ensures a clean and organized Outliner while maintaining the name of the original .dae file for easy identification.

  3. Extras Handling:Non-geometry objects like curves and empties are moved into a dedicated collection named Extras. This keeps the workspace tidy and separates non-essential elements from the main geometry.

  4. Camera Removal:Any cameras included in the .dae files are automatically deleted during the import process, preventing unnecessary clutter.

  5. Collection Organization:All imported objects are grouped under a master collection called SketchUp Importer. This collection is created automatically if it doesn’t already exist, providing a centralized location for all imported files.

  6. Blender Compatibility:The add-on is compatible with Blender 4.2.0 and later, ensuring smooth integration with the latest features and improvements in Blender.

How It Works:

  1. Folder Selection:The user selects a directory containing .dae files via the add-on’s UI in Blender.

  2. Batch Import Process:
    The add-on loops through all .dae files in the selected folder and performs the following actions for each file:Imports the .dae file into Blender.
    Identifies all newly imported objects.

  3. Object Cleanup:
    The add-on processes imported objects as follows:Geometry: All imported geometry is joined into a single object and named after the original .dae file.
    Curves and Empties: Non-geometry objects are moved into the Extras collection.
    Cameras: Any imported cameras are deleted.

  4. Organizing Collections:The main geometry object is added to the SketchUp Importer collection.
    If the SketchUp Importer or Extras collections don’t exist, the add-on creates them automatically.

  5. Final Output:
    After processing all files, the Outliner contains a clean hierarchy:
    SketchUp Importer (master collection)Individual geometry objects (one per .dae file)
    Extras collection (containing curves and empties)

  6. Enhanced Workflow:The add-on ensures a streamlined pipeline, making it easier to manage large projects with multiple tags and layers exported from SketchUp.

Intended Use:

This add-on is tailored for users who rely on SketchUp’s Ruby export script to generate .dae files for each tag or layer. By automating the import and organization process in Blender, the add-on saves time, reduces errors, and improves efficiency for architects, designers, and 3D artists.

Use Case Example:

  1. In SketchUp, a user organizes their model into layers or tags (e.g., walls, doors, windows).

  2. Using the Ruby export script, they export each tag as a .dae file.

  3. In Blender, they use the SketchUp .dae Importer add-on to batch import these files, creating a structured and clean workspace with all objects consolidated and unnecessary elements removed.

Why It’s Useful:

  • Saves significant time for users importing multiple .dae files.

  • Ensures a clean, organized Outliner with minimal manual cleanup.

  • Complements SketchUp’s layer/tag system for efficient data transfer into Blender.

bottom of page