diff --git a/io_import_dxf/__init__.py b/io_import_dxf/__init__.py index 6d2fa332a..265b70ada 100644 --- a/io_import_dxf/__init__.py +++ b/io_import_dxf/__init__.py @@ -4,10 +4,10 @@ import bpy import os -from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty, FloatProperty +from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty, FloatProperty, CollectionProperty from .dxfimport.do import Do, Indicator from .transverse_mercator import TransverseMercator - +from pathlib import Path try: from pyproj import Proj, transform @@ -83,6 +83,7 @@ T_CreateNewScene = False T_Recenter = False T_ThicknessBevel = True T_import_atts = True +T_Collection = False RELEASE_TEST = False DEBUG = False @@ -93,14 +94,14 @@ def is_ref_scene(scene): def read(report, filename, obj_merge=BY_LAYER, import_text=True, import_light=True, export_acis=True, merge_lines=True, - do_bbox=True, block_rep=LINKED_OBJECTS, new_scene=None, recenter=False, projDXF=None, projSCN=None, + do_bbox=True, block_rep=LINKED_OBJECTS, new_scene=None, new_collection=None, recenter=False, projDXF=None, projSCN=None, thicknessWidth=True, but_group_by_att=True, dxf_unit_scale=1.0): # import dxf and export nurbs types to sat/sab files # because that's how autocad stores nurbs types in a dxf... do = Do(filename, obj_merge, import_text, import_light, export_acis, merge_lines, do_bbox, block_rep, recenter, projDXF, projSCN, thicknessWidth, but_group_by_att, dxf_unit_scale) - errors = do.entities(os.path.basename(filename).replace(".dxf", ""), new_scene) + errors = do.entities(Path(filename.name).stem, new_scene, new_collection) # display errors for error in errors: @@ -192,6 +193,15 @@ class IMPORT_OT_dxf(bpy.types.Operator): filename_ext = ".dxf" + files: CollectionProperty( + type=bpy.types.OperatorFileListElement, + options={'HIDDEN', 'SKIP_SAVE'} + ) + + directory: StringProperty( + subtype='DIR_PATH' + ) + filter_glob: StringProperty( default="*.dxf", options={'HIDDEN'}, @@ -256,7 +266,23 @@ class IMPORT_OT_dxf(bpy.types.Operator): default=T_Bbox ) + scene_options: EnumProperty( + name="Scene", + description="Select the import method", + items=[('CURRENT_SCENE', "Current", "All DXF files in the current scene."), + ('NEW_SCENE', "New", "Each DXF file in a new scene."), + ('NEW_UNIQUE_SCENE', "Unique", "All DXF files in a new collection.")], + default='CURRENT_SCENE', + ) + collection_options: EnumProperty( + name="Collection", + description="Select the import method", + items=[('CURRENT_COLLECTION', "Current", "All DXF files in the current scene collection."), + ('NEW_COLLECTION', "New", "Each DXF file in a new collection."), + ('SCENE_COLLECTION', "Scene", "All DXF files in the scene collection.")], + default='CURRENT_COLLECTION', + ) block_options: EnumProperty( name="Blocks As", @@ -368,6 +394,12 @@ class IMPORT_OT_dxf(bpy.types.Operator): layout = self.layout scene = context.scene + # Import options + layout.label(text="Import Options:") + box = layout.box() + box.prop(self, "scene_options") + box.prop(self, "collection_options") + # merge options layout.label(text="Merge Options:") box = layout.box() @@ -401,7 +433,6 @@ class IMPORT_OT_dxf(bpy.types.Operator): layout.label(text="View Options:") box = layout.box() box.prop(self, "outliner_groups") - box.prop(self, "create_new_scene") sub = box.row() sub.enabled = _recenter_allowed(self) sub.prop(self, "recenter") @@ -515,13 +546,39 @@ class IMPORT_OT_dxf(bpy.types.Operator): proj_dxf = Indicator(self.dxf_indi) proj_scn = TransverseMercator(lat=self.merc_scene_lat, lon=self.merc_scene_lon) - if RELEASE_TEST: - # for release testing - from . import test - test.test() - else: - read(self.report, self.filepath, merge_options, self.import_text, self.import_light, self.export_acis, - self.merge_lines, self.do_bbox, block_map[self.block_options], scene, self.recenter, + scene = bpy.context.scene + if self.create_new_scene: + scene = bpy.data.scenes.new(Path(file.name).stem) + + for file in self.files: + + match self.scene_options: + case 'NEW_SCENE': + scene = bpy.data.scenes.new(Path(file.name).stem) + case 'NEW_UNIQUE_SCENE': + scene_name="DXF Import" + if bpy.data.scenes.get(scene_name): scene=bpy.data.scenes[scene_name] + else: scene = bpy.data.scenes.new(scene_name) + case _: + scene = bpy.context.scene + + match self.collection_options: + case 'NEW_COLLECTION': + collection = bpy.data.collections.new(Path(file.name).stem) + scene.collection.children.link(collection) + case 'SCENE_COLLECTION': + collection = scene.collection + case _: + collection = bpy.context.collection + if collection.name not in scene.collection.children: scene.collection.children.link(collection) + + if RELEASE_TEST: + # for release testing + from . import test + test.test() + else: + read(self.report, Path(self.directory, file.name), merge_options, self.import_text, self.import_light, self.export_acis, + self.merge_lines, self.do_bbox, block_map[self.block_options], scene, collection, self.recenter, proj_dxf, proj_scn, self.represent_thickness_and_width, self.import_atts, dxf_unit_scale) if self.outliner_groups: diff --git a/io_import_dxf/dxfimport/do.py b/io_import_dxf/dxfimport/do.py index 32fdafc5b..bc57bd378 100644 --- a/io_import_dxf/dxfimport/do.py +++ b/io_import_dxf/dxfimport/do.py @@ -78,7 +78,7 @@ class Do: __slots__ = ( "dwg", "combination", "known_blocks", "import_text", "import_light", "export_acis", "merge_lines", "do_bounding_boxes", "acis_files", "errors", "block_representation", "recenter", "did_group_instance", - "objects_before", "pDXF", "pScene", "thickness_and_width", "but_group_by_att", "current_scene", + "objects_before", "pDXF", "pScene", "thickness_and_width", "but_group_by_att", "current_scene", "current_collection", "dxf_unit_scale" ) @@ -104,6 +104,7 @@ class Do: self.thickness_and_width = thicknessWidth self.but_group_by_att = but_group_by_att self.current_scene = None + self.current_collection = None self.dxf_unit_scale = dxf_unit_scale def proj(self, co, elevation=0): @@ -707,7 +708,7 @@ class Do: o = bpy.data.objects.new("Point", None) o.location = self.proj(en.point) self._extrusion(o, en) - scene.collection.objects.link(o) + self.current_collection.objects.link(o) group = self._get_group(en.layer) group.objects.link(o) @@ -735,7 +736,7 @@ class Do: o.location = self.proj(en.position) dir = self.proj(en.target) - self.proj(en.position) o.rotation_quaternion = dir.rotation_difference(Vector((0, 0, -1))) - scene.collection.objects.link(o) + self.current_collection.objects.link(o) return o def mtext(self, en, scene, name): @@ -818,7 +819,7 @@ class Do: if inserts is not None: inserts.append(new_insert) new_insert.parent = parent - scene.collection.objects.link(new_insert) + self.current_collection.objects.link(new_insert) if name is None: name = entity.name @@ -850,7 +851,7 @@ class Do: if len(insert.children) > 0: i_copy = bpy.data.objects.new(insert.name, None) i_copy.matrix_basis = insert.matrix_basis - scene.collection.objects.link(i_copy) + self.current_collection.objects.link(i_copy) group.objects.link(i_copy) kids = insert.children[:] for child in kids: @@ -864,10 +865,10 @@ class Do: if len(objects) > 1 or len(insert_bounding_boxes) > 0: if self.do_bounding_boxes: o = self._object_bbox(objects + insert_bounding_boxes, name, recursion_level == 0) - scene.collection.objects.link(o) + self.current_collection.objects.link(o) else: o = bpy.data.objects.new(name, None) - scene.collection.objects.link(o) + self.current_collection.objects.link(o) if len(objects) > 0: for obj in objects: obj.parent = o @@ -877,13 +878,13 @@ class Do: else: # strange case but possible according to the testfiles o = bpy.data.objects.new(name, None) - scene.collection.objects.link(o) + self.current_collection.objects.link(o) # unlink bounding boxes of inserts for ib in insert_bounding_boxes: if ib.name in group.objects: group.objects.unlink(ib) - scene.collection.objects.unlink(ib) + self.current_collection.objects.unlink(ib) # parent inserts to this block before any transformation on the block is being applied for obj in inserts: @@ -902,11 +903,11 @@ class Do: for known_object in known_objects: oc = known_object.copy() - scene.collection.objects.link(oc) + self.current_collection.objects.link(oc) objects.append(oc) o = known_o.copy() - scene.collection.objects.link(o) + self.current_collection.objects.link(o) _recursive_copy_inserts(o, known_inserts, inserts, group, invisible) @@ -996,7 +997,7 @@ class Do: if invisible is not None: o.hide_viewport = invisible o.location = self.proj(entity.basepoint) - scene.collection.objects.link(o) + self.current_collection.objects.link(o) # block_scene.view_layers[0].update() return o @@ -1074,7 +1075,7 @@ class Do: # Blender custom property o[a.tag] = a.text attname = entity.name + "_" + a.tag - scene.collection.objects.link(self.text(a, scene, attname)) + self.current_collection.objects.link(self.text(a, scene, attname)) return o @@ -1157,7 +1158,7 @@ class Do: bevel = bpy.data.objects.new("BEVEL", bevd) obj.data.bevel_object = bevel - scene.collection.objects.link(bevel) + self.current_collection.objects.link(bevel) # CURVE TAPER if has_varying_width and len(ew) == 1: @@ -1179,7 +1180,7 @@ class Do: taper = bpy.data.objects.new("TAPER", tapd) obj.data.taper_object = taper - scene.collection.objects.link(taper) + self.current_collection.objects.link(taper) # THICKNESS FOR CURVES HAVING A WIDTH if th != 0: @@ -1217,7 +1218,7 @@ class Do: bm.to_mesh(d) o = bpy.data.objects.new(name, d) - scene.collection.objects.link(o) + self.current_collection.objects.link(o) return o def object_mesh(self, entities, scene, name): @@ -1374,7 +1375,7 @@ class Do: if type(o) == bpy.types.Object: if o.name not in scene.objects: - scene.collection.objects.link(o) + self.current_collection.objects.link(o) if o.name not in group.objects: group.objects.link(o) @@ -1447,7 +1448,7 @@ class Do: bm.to_mesh(m) o = bpy.data.objects.new(blockname, m) o.location = location - scene.collection.objects.link(o) + self.current_collection.objects.link(o) self._nest_block(o, blockname, blgroup, scene) o.instance_type = "FACES" @@ -1457,7 +1458,7 @@ class Do: def _nest_block(self, parent, name, blgroup, scene): b = self.dwg.blocks[name] e = bpy.data.objects.new(name, None) - scene.collection.objects.link(e) + self.current_collection.objects.link(e) #e.location = parent.location e.parent = parent for TYPE, grouped in groupsort.by_dxftype(b): @@ -1593,14 +1594,18 @@ class Do: return objects - def entities(self, name, scene=None): + def entities(self, name, scene=None, collection=None): """ Iterates over all DXF entities according to the options set by user. """ if scene is None: scene = bpy.context.scene + if collection is None: + collection = scene.collection + self.current_scene = scene + self.current_collection = collection if self.recenter: self.objects_before += scene.objects[:]