# SPDX-License-Identifier: Apache-2.0 # Copyright 2018-2021 The glTF-Blender-IO authors. from ..com.gltf2_io import gltf_from_dict from ..com.gltf2_io_debug import Log import logging import json import struct import base64 from os.path import dirname, join, isfile from urllib.parse import unquote # Raise this error to have the importer report an error message. class ImportError(RuntimeError): pass class glTFImporter(): """glTF Importer class.""" def __init__(self, filename, import_settings): """initialization.""" self.filename = filename self.import_settings = import_settings self.glb_buffer = None self.buffers = {} self.accessor_cache = {} self.decode_accessor_cache = {} self.import_user_extensions = import_settings['import_user_extensions'] self.variant_mapping = {} # Used to map between mgltf material idx and blender material, for Variants if 'loglevel' not in self.import_settings.keys(): self.import_settings['loglevel'] = logging.ERROR log = Log(import_settings['loglevel']) self.log = log.logger self.log_handler = log.hdlr # TODO: move to a com place? self.extensions_managed = [ 'KHR_materials_pbrSpecularGlossiness', 'KHR_lights_punctual', 'KHR_materials_unlit', 'KHR_texture_transform', 'KHR_materials_clearcoat', 'KHR_mesh_quantization', 'KHR_draco_mesh_compression', 'KHR_materials_variants', 'KHR_materials_emissive_strength', 'KHR_materials_transmission', 'KHR_materials_specular', 'KHR_materials_sheen', 'KHR_materials_ior' ] # Add extensions required supported by custom import extensions for import_extension in self.import_user_extensions: if hasattr(import_extension, "extensions"): for custom_extension in import_extension.extensions: if custom_extension.required: self.extensions_managed.append(custom_extension.name) @staticmethod def load_json(content): def bad_constant(val): raise ImportError('Bad glTF: json contained %s' % val) try: text = str(content, encoding='utf-8') return json.loads(text, parse_constant=bad_constant) except ValueError as e: raise ImportError('Bad glTF: json error: %s' % e.args[0]) @staticmethod def check_version(gltf): """Check version. This is done *before* gltf_from_dict.""" if not isinstance(gltf, dict) or 'asset' not in gltf: raise ImportError("Bad glTF: no asset in json") if 'version' not in gltf['asset']: raise ImportError("Bad glTF: no version") if gltf['asset']['version'] != "2.0": raise ImportError("glTF version must be 2.0; got %s" % gltf['asset']['version']) def checks(self): """Some checks.""" if self.data.extensions_required is not None: for extension in self.data.extensions_required: if extension not in self.data.extensions_used: raise ImportError("Extension required must be in Extension Used too") if extension not in self.extensions_managed: raise ImportError("Extension %s is not available on this addon version" % extension) if self.data.extensions_used is not None: for extension in self.data.extensions_used: if extension not in self.extensions_managed: # Non blocking error #TODO log pass def load_glb(self, content): """Load binary glb.""" magic = content[:4] if magic != b'glTF': raise ImportError("This file is not a glTF/glb file") version, file_size = struct.unpack_from('