From 60a11a0fc4426f01e87be0e019c5d909889e511e Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Sun, 29 Dec 2019 13:05:31 +0100 Subject: glTF exporter: add option to export textures into a folder --- io_scene_gltf2/__init__.py | 20 +++++++++++-- io_scene_gltf2/blender/exp/gltf2_blender_export.py | 10 ++----- .../blender/exp/gltf2_blender_export_keys.py | 1 + .../blender/exp/gltf2_blender_gltf2_exporter.py | 34 ++++++++++++++++------ 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 40beaca1..78141088 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -15,7 +15,7 @@ bl_info = { 'name': 'glTF 2.0 format', 'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', - "version": (1, 1, 26), + "version": (1, 1, 27), 'blender': (2, 81, 6), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', @@ -127,6 +127,12 @@ class ExportGLTF2_Base: default='NAME' ) + export_texture_dir: StringProperty( + name='Textures', + description='Folder to place texture files in. Relative to the .gltf file', + default='', + ) + export_texcoords: BoolProperty( name='UVs', description='Export UVs (texture coordinates) with meshes', @@ -347,7 +353,8 @@ class ExportGLTF2_Base: del context.scene[self.scene_key] import sys - for addon_name in bpy.context.preferences.addons.keys(): + preferences = bpy.context.preferences + for addon_name in preferences.addons.keys(): try: if hasattr(sys.modules[addon_name], 'glTF2ExportUserExtension'): extension_panel_unregister_functors.append(sys.modules[addon_name].register_panel()) @@ -385,6 +392,10 @@ class ExportGLTF2_Base: export_settings['gltf_filepath'] = bpy.path.ensure_ext(self.filepath, self.filename_ext) export_settings['gltf_filedirectory'] = os.path.dirname(export_settings['gltf_filepath']) + '/' + export_settings['gltf_texturedirectory'] = os.path.join( + export_settings['gltf_filedirectory'], + self.export_texture_dir, + ) export_settings['gltf_format'] = self.export_format export_settings['gltf_image_format'] = self.export_image_format @@ -452,7 +463,8 @@ class ExportGLTF2_Base: user_extensions = [] import sys - for addon_name in bpy.context.preferences.addons.keys(): + preferences = bpy.context.preferences + for addon_name in preferences.addons.keys(): if hasattr(sys.modules[addon_name], 'glTF2ExportUserExtension'): extension_ctor = sys.modules[addon_name].glTF2ExportUserExtension user_extensions.append(extension_ctor()) @@ -492,6 +504,8 @@ class GLTF_PT_export_main(bpy.types.Panel): operator = sfile.active_operator layout.prop(operator, 'export_format') + if operator.export_format == 'GLTF_SEPARATE': + layout.prop(operator, 'export_texture_dir', icon='FILE_FOLDER') layout.prop(operator, 'export_copyright') layout.prop(operator, 'will_save_settings') diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_export.py b/io_scene_gltf2/blender/exp/gltf2_blender_export.py index 06af24cc..94babf78 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_export.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_export.py @@ -49,21 +49,15 @@ def save(context, export_settings): def __export(export_settings): - exporter = GlTF2Exporter(__get_copyright(export_settings)) + exporter = GlTF2Exporter(export_settings) __gather_gltf(exporter, export_settings) buffer = __create_buffer(exporter, export_settings) - exporter.finalize_images(export_settings[gltf2_blender_export_keys.FILE_DIRECTORY]) + exporter.finalize_images() json = __fix_json(exporter.glTF.to_dict()) return json, buffer -def __get_copyright(export_settings): - if export_settings[gltf2_blender_export_keys.COPYRIGHT]: - return export_settings[gltf2_blender_export_keys.COPYRIGHT] - return None - - def __gather_gltf(exporter, export_settings): active_scene_idx, scenes, animations = gltf2_blender_gather.gather_gltf2(export_settings) diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_export_keys.py b/io_scene_gltf2/blender/exp/gltf2_blender_export_keys.py index a8daa6b4..8813337b 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_export_keys.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_export_keys.py @@ -35,6 +35,7 @@ JOINT_CACHE = 'gltf_joint_cache' COPYRIGHT = 'gltf_copyright' FORMAT = 'gltf_format' FILE_DIRECTORY = 'gltf_filedirectory' +TEXTURE_DIRECTORY = 'gltf_texturedirectory' BINARY_FILENAME = 'gltf_binaryfilename' YUP = 'gltf_yup' MORPH = 'gltf_morph' diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py b/io_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py index fe50b407..2c44a018 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. import re +import os +import urllib.parse from typing import List from ... import get_version_string @@ -20,6 +22,7 @@ from io_scene_gltf2.io.com import gltf2_io_extensions from io_scene_gltf2.io.exp import gltf2_io_binary_data from io_scene_gltf2.io.exp import gltf2_io_buffer from io_scene_gltf2.io.exp import gltf2_io_image_data +from io_scene_gltf2.blender.exp import gltf2_blender_export_keys class GlTF2Exporter: @@ -29,9 +32,11 @@ class GlTF2Exporter: Any child properties are replaced with references where necessary """ - def __init__(self, copyright=None): + def __init__(self, export_settings): + self.export_settings = export_settings self.__finalized = False + copyright = export_settings[gltf2_blender_export_keys.COPYRIGHT] or None asset = gltf2_io.Asset( copyright=copyright, extensions=None, @@ -143,14 +148,15 @@ class GlTF2Exporter: self.__gltf.extensions_required.append('KHR_draco_mesh_compression') self.__gltf.extensions_used.append('KHR_draco_mesh_compression') - def finalize_images(self, output_path): + def finalize_images(self): """ Write all images. - - Due to a current limitation the output_path must be the same as that of the glTF file - :param output_path: - :return: """ + output_path = self.export_settings[gltf2_blender_export_keys.TEXTURE_DIRECTORY] + + if self.__images: + os.makedirs(output_path, exist_ok=True) + for name, image in self.__images.items(): dst_path = output_path + "/" + name + image.file_extension with open(dst_path, 'wb') as f: @@ -222,12 +228,17 @@ class GlTF2Exporter: name += "-" + str(count) count += 1 - # TODO: we need to know the image url at this point already --> maybe add all options to the constructor of the - # exporter # TODO: allow embedding of images (base64) self.__images[name] = image - return name + image.file_extension + + texture_dir = self.export_settings[gltf2_blender_export_keys.TEXTURE_DIRECTORY] + abs_path = os.path.join(texture_dir, name + image.file_extension) + rel_path = os.path.relpath( + abs_path, + start=self.export_settings[gltf2_blender_export_keys.FILE_DIRECTORY], + ) + return _path_to_uri(rel_path) @classmethod def __get_key_path(cls, d: dict, keypath: List[str], default): @@ -313,3 +324,8 @@ class GlTF2Exporter: # do nothing for any type that does not match a glTF schema (primitives) return node +def _path_to_uri(path): + path = os.path.normpath(path) + path = path.replace(os.sep, '/') + return urllib.parse.quote(path) + -- cgit v1.2.3