├── prefs.png ├── README.md └── importscad.py /prefs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maqqr/blender-openscad-import/HEAD/prefs.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | blender-openscad-import 2 | ======================= 3 | 4 | Blender importer for [OpenSCAD](http://www.openscad.org) files. 5 | 6 | You need to have OpenSCAD installed on your computer for this addon to work. 7 | 8 | How to install 9 | -------------- 10 | 11 | 1. Download the addon by right clicking [this file](https://raw.githubusercontent.com/maqqr/blender-openscad-import/master/importscad.py) and choosing Save Link As... 12 | 2. In Blender, go to **File > User Preferences** and select **Install from File** and then select importscad.py 13 | 3. Set OpenSCAD executable path in the addon preferences (see image below). 14 | 15 | On Linux-based systems, your OpenSCAD executable location is most likely `/usr/bin/openscad` if it was installed using `apt-get`. 16 | 17 | ![Addon preferences](/prefs.png) 18 | -------------------------------------------------------------------------------- /importscad.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import subprocess 4 | import bpy 5 | from bpy.props import StringProperty, BoolProperty, FloatProperty, IntProperty, PointerProperty, CollectionProperty 6 | from bpy.types import Operator, AddonPreferences 7 | from bpy_extras.io_utils import ImportHelper 8 | 9 | 10 | bl_info = { 11 | "name": "OpenSCAD importer", 12 | "description": "Imports OpenSCAD (.scad) files.", 13 | "author": "Maqq", 14 | "version": (1, 3), 15 | "blender": (2, 80, 0), 16 | "location": "File > Import", 17 | "warning": "", # used for warning icon and text in addons panel 18 | "category": "Import-Export" 19 | } 20 | 21 | # Temporary stl file 22 | TEMPNAME = "tempexport.stl" 23 | 24 | 25 | def read_openscad(context, filepath, scale, parameters): 26 | """ Exports stl using OpenSCAD and imports it. """ 27 | from io_mesh_stl import stl_utils 28 | from io_mesh_stl import blender_utils 29 | from mathutils import Matrix 30 | 31 | user_preferences = bpy.context.preferences 32 | addon_prefs = user_preferences.addons[__name__].preferences 33 | openscad_path = addon_prefs.filepath 34 | tempfile_path = os.path.join(os.path.dirname(filepath), TEMPNAME) 35 | 36 | # Export stl from OpenSCAD 37 | command = [openscad_path, "-o", tempfile_path, filepath] 38 | 39 | print("Executing command:", command) 40 | use_shell = False if os.name == 'posix' else True 41 | result = subprocess.run(command, capture_output=True, shell=use_shell, text=True) 42 | print(result.stdout) 43 | print(result.stderr) 44 | 45 | if os.path.exists(tempfile_path): 46 | if bpy.ops.object.mode_set.poll(): 47 | bpy.ops.object.mode_set(mode='OBJECT') 48 | 49 | if bpy.ops.object.select_all.poll(): 50 | bpy.ops.object.select_all(action='DESELECT') 51 | 52 | obj_name = os.path.basename(filepath).split('.')[0] 53 | bpy.ops.import_mesh.stl(filepath=tempfile_path, global_scale=scale) 54 | os.remove(tempfile_path) 55 | 56 | # Rename the imported stl objects 57 | for imported_obj in bpy.context.selected_objects: 58 | imported_obj.name = obj_name 59 | imported_obj.data.name = obj_name 60 | 61 | else: 62 | print("Temporary export file not found:", tempfile_path) 63 | 64 | return {'FINISHED'} 65 | 66 | 67 | class OpenSCADImporterPreferences(AddonPreferences): 68 | """ Addon preferences. """ 69 | bl_idname = __name__ 70 | 71 | filepath : StringProperty( 72 | name="Path to OpenSCAD executable", 73 | subtype='FILE_PATH', 74 | ) 75 | 76 | def draw(self, context): 77 | self.layout.prop(self, "filepath") 78 | 79 | 80 | class OpenSCADImporter(Operator, ImportHelper): 81 | """ Import OpenSCAD files. """ 82 | bl_idname = "import_mesh.scad" 83 | bl_label = "Import OpenSCAD" 84 | 85 | # ImportHelper mixin class uses this 86 | filename_ext = ".scad" 87 | 88 | filter_glob : StringProperty( 89 | default="*.scad", 90 | options={'HIDDEN'}, 91 | ) 92 | 93 | scale : FloatProperty(name='Scale', default=1.0) 94 | 95 | # Parameters for the scad file 96 | p1 : StringProperty(name='P1 name') 97 | p1v : StringProperty(name='P1 value') 98 | p2 : StringProperty(name='P2 name') 99 | p2v : StringProperty(name='P2 value') 100 | p3 : StringProperty(name='P3 name') 101 | p3v : StringProperty(name='P3 value') 102 | p4 : StringProperty(name='P4 name') 103 | p4v : StringProperty(name='P4 value') 104 | 105 | def __init__(self): 106 | super(OpenSCADImporter, self).__init__() 107 | 108 | def execute(self, context): 109 | return read_openscad(context, self.filepath, self.scale, {self.p1:self.p1v, self.p2:self.p2v, self.p3:self.p3v, self.p4:self.p4v}) 110 | 111 | 112 | def menu_func_import(self, context): 113 | self.layout.operator(OpenSCADImporter.bl_idname, text="OpenSCAD (.scad)") 114 | 115 | def register(): 116 | bpy.utils.register_class(OpenSCADImporter) 117 | bpy.utils.register_class(OpenSCADImporterPreferences) 118 | bpy.types.TOPBAR_MT_file_import.append(menu_func_import) 119 | 120 | def unregister(): 121 | bpy.utils.unregister_class(OpenSCADImporter) 122 | bpy.types.TOPBAR_MT_file_import.append(menu_func_import) 123 | 124 | if __name__ == "__main__": 125 | pass 126 | --------------------------------------------------------------------------------