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