Fix T78854: Cell fracture fails in background mode
[blender-addons.git] / io_export_dxf / export_dxf.py
blobf763b3a39aa5d378e9e217539890fb76165277ce
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 import os
4 import mathutils
6 DEBUG = os.environ.get('BLENDER_DEBUG', False) #activates debug mode
7 if DEBUG:
8 import sys
9 sys.path.append(os.environ['PYDEV_DEBUG_PATH'])
10 import pydevd
12 from .model.migiusModel import MigiusDXFLibDrawing
14 SUPPORTED_TYPES = ('MESH')#,'CURVE','EMPTY','TEXT','CAMERA','LIGHT')
16 def exportDXF(context, filePath, settings):
17 """
18 Main entry point into export facility.
19 """
20 print("----------\nExporting to {}".format(filePath))
21 import time
22 time1 = time.perf_counter()
24 if settings['verbose']:
25 print("Generating Object list for export... (Root parents only)")
27 scene = context.scene
29 if settings['onlySelected'] is True:
30 objects = (ob for ob in scene.objects if not ob.hide_viewport and ob.select_get() and ob.type in SUPPORTED_TYPES)
31 else:
32 objects = (ob for ob in scene.objects if not ob.hide_viewport and ob.type in SUPPORTED_TYPES)
34 if DEBUG: pydevd.settrace()
35 mw = get_view_projection_matrix(context, settings)
37 try:
38 # add Entities --------------------
39 #todo: fixme: seems to be the reason for missing BLOCK-export
40 #if APPLY_MODIFIERS: tmp_me = Mesh.New('tmp')
41 #else: tmp_me = None
43 drawing = MigiusDXFLibDrawing()
44 exported = 0
45 for o in objects:
46 if _exportItem(context, o, mw, drawing, settings):
47 exported +=1
49 if not drawing.isEmpty():
50 # NOTE: Only orthographic projection used now.
51 # if PERSPECTIVE: # generate view border - passepartout
52 # from .primitive_exporters.viewborder_exporter import ViewBorderDXFExporter
53 # e = ViewBorderDXFExporter(settings)
54 # e.export(drawing, ob, mx, mw)
56 drawing.convert(filePath)
58 duration = time.perf_counter() - time1
59 print('%s objects exported in %.2f seconds. -----DONE-----' %\
60 (exported, duration))
61 except IOError:
62 print('DXF Exporter: Write Error: ', filePath)
63 except Exception as e:
64 print('Nothing exported. Error: %s' % str(e))
66 print("Finished")
68 #-------------------------------------------------
69 def getCommons(ob, settings):
70 """set up common attributes for output style:
71 color=None
72 extrusion=None
73 layer='0',
74 lineType=None
75 lineTypeScale=None
76 lineWeight=None
77 thickness=None
78 parent=None
79 """
81 BYBLOCK=0 #DXF-attribute: assign property to BLOCK defaults
82 BYLAYER=None #256 #DXF-attribute: assign property to LAYER defaults
83 LAYERNAME_DEF='' #default layer name
84 LAYERCOLOR_DEF=7 #default layer color index
85 LAYERLTYPE_DEF=0 #'CONTINUOUS' - default layer lineType
86 ENTITYLAYER_DEF=LAYERNAME_DEF #default entity color index
87 ENTITYCOLOR_DEF=BYLAYER #default entity color index
88 ENTITYLTYPE_DEF=BYLAYER #default entity lineType
90 #layers = ob.layers #gives a list e.g.[1,5,19]
91 layers = ob.users_collection
92 if layers: ob_layer_nr = layers[0]
93 if DEBUG: print('ob_layer_nr=', ob_layer_nr) #--------------
95 materials = ob.material_slots
96 if materials:
97 ob_material = materials[0]
98 ob_mat_color = ob_material.material.diffuse_color
99 else: ob_mat_color, ob_material = None, None
100 if DEBUG:
101 print('ob_mat_color, ob_material=', ob_mat_color, ob_material) #--------------
103 data_materials = ob.material_slots
104 if data_materials:
105 data_material = data_materials[0]
106 data_mat_color = data_material.material.diffuse_color
107 else: data_mat_color, data_material = None, None
108 if DEBUG:
109 print('data_mat_color, data_material=', data_mat_color, data_material) #--------------
111 entitylayer = ENTITYLAYER_DEF
112 c = settings['entitylayer_from']
113 #["default_LAYER","obj.name","obj.layer","obj.material","obj.data.name","obj.data.material","..vertexgroup","..group","..map_table"]
114 if c=="default_LAYER":
115 entitylayer = LAYERNAME_DEF
116 elif c=="obj.layer" and ob_layer_nr:
117 entitylayer = 'LAYER'+ str(ob_layer_nr)
118 elif c=="obj.material" and ob_material:
119 entitylayer = ob_material.name
120 elif c=="obj.name":
121 entitylayer = ob.name
122 elif c=="obj.data.material" and ob_material:
123 entitylayer = data_material.name
124 elif c=="obj.data.name":
125 entitylayer = ob.data.name
127 entitycolor = ENTITYCOLOR_DEF
128 cfrom = settings['entitycolor_from']
129 if cfrom=="default_COLOR":
130 entitycolor = LAYERCOLOR_DEF
131 elif cfrom=="BYLAYER":
132 entitycolor = BYLAYER
133 elif cfrom=="BYBLOCK":
134 entitycolor = BYBLOCK
135 elif cfrom=="obj.layer" and ob_layer_nr:
136 entitycolor = ob_layer_nr
137 elif cfrom=="obj.color" and ob.color:
138 entitycolor = ob.color
139 elif cfrom=="obj.material" and ob_mat_color:
140 entitycolor = ob_mat_color
141 elif cfrom=="obj.data.material" and data_mat_color:
142 entitycolor = data_mat_color
144 entityltype = ENTITYLTYPE_DEF
145 etype = settings['entityltype_from']
146 if etype=="default_LTYPE":
147 entityltype = LAYERLTYPE_DEF
148 elif etype=="BYLAYER":
149 entityltype = BYLAYER
150 elif etype=="BYBLOCK":
151 entityltype = BYBLOCK
152 elif etype:
153 entityltype = etype
155 return entitylayer, entitycolor, entityltype
157 def getCameraMatrix(cam):
158 raise NotImplementedError()
159 # camProps = cam.data
160 # mc0 = act_camera.matrix.copy()
161 # #print 'deb: camera.Matrix=\n', mc0 #------------------
162 # camera = Camera.Get(act_camera.getData(name_only=True))
163 # #print 'deb: camera=', dir(camera) #------------------
164 # if camera.type=='persp': PERSPECTIVE = 1
165 # elif camera.type=='ortho': PERSPECTIVE = 0
166 # # mcp is matrix.camera.perspective
167 # clip_box, mcp = getClipBox(camera)
168 ## if PERSPECTIVE:
169 ## # get border
170 ## # lens = camera.lens
171 ## min_X1, max_X1, min_Y1, max_Y1,\
172 ## min_X2, max_X2, min_Y2, max_Y2,\
173 ## min_Z, max_Z = clip_box
174 ## verts = []
175 ## verts.append([min_X1, min_Y1, min_Z])
176 ## verts.append([max_X1, min_Y1, min_Z])
177 ## verts.append([max_X1, max_Y1, min_Z])
178 ## verts.append([min_X1, max_Y1, min_Z])
179 ## border=verts
180 # mw = mc0.copy().invert()
181 # #ViewVector = mathutils.Vector(Window.GetViewVector())
182 # #print 'deb: ViewVector=\n', ViewVector #------------------
183 # #TODO: what is Window.GetViewOffset() for?
184 # #print 'deb: Window.GetViewOffset():', Window.GetViewOffset() #---------
185 # #Window.SetViewOffset([0,0,0])
186 # mw0 = Window.GetViewMatrix()
187 # #print 'deb: mwOrtho =\n', mw0 #---------
188 # mwp = Window.GetPerspMatrix() #TODO: how to get it working?
189 # #print 'deb: mwPersp =\n', mwp #---------
190 # mw = mw0.copy()
192 projectionMapping = {
193 'TOP' : mathutils.Vector((0, 0, -1)),
194 'BOTTOM' : mathutils.Vector((0, 0, 1)),
195 'LEFT' : mathutils.Vector((0, 1, 0)),
196 'RIGHT' : mathutils.Vector((0, -1, 0)),
197 'FRONT' : mathutils.Vector((-1, 0, 0)),
198 'REAR' : mathutils.Vector((1, 0, 0))
201 #-----------------------------------------------------
202 def get_view_projection_matrix(context, settings):
204 Returns view projection matrix.
205 Projection matrix is either identity if 3d export is selected or
206 camera projection if a camera or view is selected.
207 Currently only orthographic projection is used. (Subject to discussion).
209 cam = settings['projectionThrough']
210 if cam is None:
211 mw = mathutils.Matrix()
212 mw.identity()
213 elif cam in projectionMapping.keys():
214 projection = mathutils.Matrix.OrthoProjection(projectionMapping[cam], 4)
215 mw = projection
216 else: # get camera with given name
217 c = context.scene.collection.objects[cam]
218 mw = getCameraMatrix(c)
219 return mw
221 def _exportItem(ctx, o, mw, drawing, settings):
223 Export one item from export list.
224 mw - modelview
226 if settings['verbose']: print('Exporting %s' % o)
227 #mx = ob.matrix.copy()
228 #print 'deb: ob =', ob #---------
229 #print 'deb: ob.type =', ob.type #---------
230 #print 'deb: mx =\n', mx #---------
231 #print 'deb: mw0 =\n', mw0 #---------
232 #mx_n is trans-matrix for normal_vectors for front-side faces
233 mx = o.matrix_world
234 viewRotation = mw.to_euler().to_matrix()
235 mx_n = o.rotation_euler.to_matrix() @ viewRotation
236 mx @= mw
238 #mx_inv = mx.copy().invert()
239 elayer, ecolor, eltype = getCommons(o, settings)
240 if settings['verbose']:
241 print('elayer=%s, ecolor=%s, eltype=%s' % (elayer, ecolor, eltype))
242 #TODO: use o.boundBox for drawing extends ??
244 if elayer is not None and not drawing.containsLayer(elayer):
245 if ecolor is not None: tempcolor = ecolor
246 else: tempcolor = settings['layercolor_def']
247 drawing.addLayer(elayer, tempcolor)
249 if DEBUG: pydevd.settrace()
250 if (o.type == 'MESH') and settings['mesh_as']:
251 from .primitive_exporters.mesh_exporter import MeshDXFExporter
252 e = MeshDXFExporter(settings)
253 elif (o.type == 'CURVE') and settings['curve_as']:
254 from .primitive_exporters.curve_exporter import CurveDXFExporter
255 e = CurveDXFExporter(settings)
256 elif (o.type == 'EMPTY') and settings['empty_as']:
257 from .primitive_exporters.empty_exporter import EmptyDXFExporter
258 e = EmptyDXFExporter(settings)
259 elif (o.type == 'TEXT') and settings['text_as']:
260 from .primitive_exporters.text_exporter import TextDXFExporter
261 e = TextDXFExporter(settings)
262 elif (o.type == 'CAMERA') and settings['camera_as']:
263 from .primitive_exporters.camera_exporter import CameraDXFExporter
264 e = CameraDXFExporter(settings)
265 elif (o.type == 'LIGHT') and settings['light_as']:
266 from .primitive_exporters.light_exporter import LampDXFExporter
267 e = LampDXFExporter(settings)
269 return e.export(ctx, drawing, o, mx, mx_n, color=ecolor, layer=elayer, lineType=eltype)