glTF exporter: add option to export textures into a folder

This commit is contained in:
Julien Duroure 2019-12-29 13:05:31 +01:00
parent a659ebbd5d
commit 60a11a0fc4
4 changed files with 45 additions and 20 deletions

View File

@ -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')

View File

@ -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)

View File

@ -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'

View File

@ -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)