1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
21 # Export wrappers and integration with external tools.
27 def image_copy_guess(filepath
, objects
):
28 # 'filepath' is the path we are writing to.
30 from bpy_extras
import object_utils
33 image
= object_utils
.object_image_guess(obj
)
38 imagepath
= bpy
.path
.abspath(image
.filepath
, library
=image
.library
)
39 if os
.path
.exists(imagepath
):
40 filepath_noext
= os
.path
.splitext(filepath
)[0]
41 ext
= os
.path
.splitext(imagepath
)[1]
43 imagepath_dst
= filepath_noext
+ ext
44 print("copying texture: %r -> %r" % (imagepath
, imagepath_dst
))
46 shutil
.copy(imagepath
, imagepath_dst
)
52 def write_mesh(context
, info
, report_cb
):
54 unit
= scene
.unit_settings
55 print_3d
= scene
.print_3d
57 obj_base
= scene
.object_bases
.active
60 export_format
= print_3d
.export_format
61 global_scale
= unit
.scale_length
if (unit
.system
!= 'NONE' and print_3d
.use_apply_scale
) else 1.0
62 path_mode
= 'COPY' if print_3d
.use_export_texture
else 'AUTO'
64 context_override
= context
.copy()
68 # PLY can only export single mesh objects!
69 if export_format
== 'PLY':
70 context_backup
= context
.copy()
71 bpy
.ops
.object.mode_set(mode
='OBJECT', toggle
=False)
73 from . import mesh_helpers
74 obj_base_tmp
= mesh_helpers
.object_merge(context
, context_override
["selected_objects"])
75 context_override
["active_object"] = obj_base_tmp
.object
76 context_override
["selected_bases"] = [obj_base_tmp
]
77 context_override
["selected_objects"] = [obj_base_tmp
.object]
79 if obj_base
not in context_override
["selected_bases"]:
80 context_override
["selected_bases"].append(obj_base
)
81 if obj
not in context_override
["selected_objects"]:
82 context_override
["selected_objects"].append(obj
)
84 export_path
= bpy
.path
.abspath(print_3d
.export_path
)
86 # Create name 'export_path/blendname-objname'
87 # add the filename component
89 name
= os
.path
.basename(bpy
.data
.filepath
)
90 name
= os
.path
.splitext(name
)[0]
94 name
+= "-%s" % bpy
.path
.clean_name(obj
.name
)
96 # first ensure the path is created
98 # this can fail with strange errors,
99 # if the dir cant be made then we get an error later.
101 os
.makedirs(export_path
, exist_ok
=True)
104 traceback
.print_exc()
106 filepath
= os
.path
.join(export_path
, name
)
108 # ensure addon is enabled
111 def addon_ensure(addon_id
):
112 # Enable the addon, dont change preferences.
113 default_state
, loaded_state
= addon_utils
.check(addon_id
)
115 addon_utils
.enable(addon_id
, default_set
=False)
117 if export_format
== 'STL':
118 addon_ensure("io_mesh_stl")
119 filepath
= bpy
.path
.ensure_ext(filepath
, ".stl")
120 ret
= bpy
.ops
.export_mesh
.stl(
124 use_mesh_modifiers
=True,
125 global_scale
=global_scale
,
127 elif export_format
== 'PLY':
128 addon_ensure("io_mesh_ply")
129 filepath
= bpy
.path
.ensure_ext(filepath
, ".ply")
130 ret
= bpy
.ops
.export_mesh
.ply(
133 use_mesh_modifiers
=True,
134 global_scale
=global_scale
,
136 elif export_format
== 'X3D':
137 addon_ensure("io_scene_x3d")
138 filepath
= bpy
.path
.ensure_ext(filepath
, ".x3d")
139 ret
= bpy
.ops
.export_scene
.x3d(
142 use_mesh_modifiers
=True,
145 global_scale
=global_scale
,
147 elif export_format
== 'WRL':
148 addon_ensure("io_scene_vrml2")
149 filepath
= bpy
.path
.ensure_ext(filepath
, ".wrl")
150 ret
= bpy
.ops
.export_scene
.vrml2(
153 use_mesh_modifiers
=True,
156 global_scale
=global_scale
,
158 elif export_format
== 'OBJ':
159 addon_ensure("io_scene_obj")
160 filepath
= bpy
.path
.ensure_ext(filepath
, ".obj")
161 ret
= bpy
.ops
.export_scene
.obj(
164 use_mesh_modifiers
=True,
167 global_scale
=global_scale
,
172 # for formats that don't support images
173 if export_format
in {'STL', 'PLY'}:
174 if path_mode
== 'COPY':
175 image_copy_guess(filepath
, context_override
["selected_objects"])
177 if obj_base_tmp
is not None:
178 obj
= obj_base_tmp
.object
180 scene
.objects
.unlink(obj
)
181 bpy
.data
.objects
.remove(obj
)
182 bpy
.data
.meshes
.remove(mesh
)
183 del obj_base_tmp
, obj
, mesh
187 for base
in context_backup
["selected_bases"]:
190 scene
.objects
.active
= context_backup
["active_object"]
192 if 'FINISHED' in ret
:
193 info
.append(("%r ok" % os
.path
.basename(filepath
), None))
195 if report_cb
is not None:
196 report_cb({'INFO'}, "Exported: %r" % filepath
)
199 info
.append(("%r fail" % os
.path
.basename(filepath
), None))