Newer
Older
bl_idname = 'import_scene.gltf'
bl_label = 'Import glTF 2.0'
bl_options = {'REGISTER', 'UNDO'}
filter_glob: StringProperty(default="*.glb;*.gltf", options={'HIDDEN'})
files: CollectionProperty(
name="File Path",
type=bpy.types.OperatorFileListElement,
)
loglevel: IntProperty(
name='Log Level',
description="Log Level")
import_pack_images: BoolProperty(
name='Pack Images',
description='Pack all images into .blend file',
default=True
)
merge_vertices: BoolProperty(
name='Merge Vertices',
description=(
'The glTF format requires discontinuous normals, UVs, and '
'other vertex attributes to be stored as separate vertices, '
'as required for rendering on typical graphics hardware. '
'This option attempts to combine co-located vertices where possible. '
'Currently cannot combine verts with different normals'
),
default=False,
)
import_shading: EnumProperty(
name="Shading",
items=(("NORMALS", "Use Normal Data", ""),
("FLAT", "Flat Shading", ""),
("SMOOTH", "Smooth Shading", "")),
description="How normals are computed during import",
default="NORMALS")
bone_heuristic: EnumProperty(
name="Bone Dir",
items=(
("BLENDER", "Blender (best for re-importing)",
"Good for re-importing glTFs exported from Blender. "
"Bone tips are placed on their local +Y axis (in glTF space)"),
("TEMPERANCE", "Temperance (average)",
"Decent all-around strategy. "
"A bone with one child has its tip placed on the local axis "
"closest to its child"),
("FORTUNE", "Fortune (may look better, less accurate)",
"Might look better than Temperance, but also might have errors. "
"A bone with one child has its tip placed at its child's root. "
"Non-uniform scalings may get messed up though, so beware"),
),
description="Heuristic for placing bones. Tries to make bones pretty",
default="TEMPERANCE",
)
guess_original_bind_pose: BoolProperty(
name='Guess Original Bind Pose',
description=(
'Try to guess the original bind pose for skinned meshes from '
'When off, use default/rest pose as bind pose'
),
default=True,
)
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
layout.prop(self, 'import_pack_images')
layout.prop(self, 'merge_vertices')
layout.prop(self, 'import_shading')
layout.prop(self, 'guess_original_bind_pose')
layout.prop(self, 'bone_heuristic')
def invoke(self, context, event):
import sys
preferences = bpy.context.preferences
for addon_name in preferences.addons.keys():
try:
if hasattr(sys.modules[addon_name], 'glTF2ImportUserExtension') or hasattr(sys.modules[addon_name], 'glTF2ImportUserExtensions'):
importer_extension_panel_unregister_functors.append(sys.modules[addon_name].register_panel())
except Exception:
pass
self.has_active_importer_extensions = len(importer_extension_panel_unregister_functors) > 0
return ImportHelper.invoke(self, context, event)
def execute(self, context):
return self.import_gltf2(context)
def import_gltf2(self, context):
import os
self.set_debug_log()
import_settings = self.as_keywords()
user_extensions = []
import sys
preferences = bpy.context.preferences
for addon_name in preferences.addons.keys():
try:
module = sys.modules[addon_name]
except Exception:
continue
if hasattr(module, 'glTF2ImportUserExtension'):
extension_ctor = module.glTF2ImportUserExtension
user_extensions.append(extension_ctor())
import_settings['import_user_extensions'] = user_extensions
if self.files:
# Multiple file import
ret = {'CANCELLED'}
dirname = os.path.dirname(self.filepath)
for file in self.files:
path = os.path.join(dirname, file.name)
if self.unit_import(path, import_settings) == {'FINISHED'}:
ret = {'FINISHED'}
return ret
else:
# Single file import
return self.unit_import(self.filepath, import_settings)
def unit_import(self, filename, import_settings):
import time
from .io.imp.gltf2_io_gltf import glTFImporter, ImportError
from .blender.imp.gltf2_blender_gltf import BlenderGlTF
try:
gltf_importer = glTFImporter(filename, import_settings)
gltf_importer.read()
gltf_importer.checks()
print("Data are loaded, start creating Blender stuff")
start_time = time.time()
BlenderGlTF.create(gltf_importer)
elapsed_s = "{:.2f}s".format(time.time() - start_time)
print("glTF import finished in " + elapsed_s)
gltf_importer.log.removeHandler(gltf_importer.log_handler)
return {'FINISHED'}
except ImportError as e:
self.report({'ERROR'}, e.args[0])
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
return {'CANCELLED'}
def set_debug_log(self):
import logging
if bpy.app.debug_value == 0:
self.loglevel = logging.CRITICAL
elif bpy.app.debug_value == 1:
self.loglevel = logging.ERROR
elif bpy.app.debug_value == 2:
self.loglevel = logging.WARNING
elif bpy.app.debug_value == 3:
self.loglevel = logging.INFO
else:
self.loglevel = logging.NOTSET
def menu_func_import(self, context):
self.layout.operator(ImportGLTF2.bl_idname, text='glTF 2.0 (.glb/.gltf)')
classes = (
ExportGLTF2,
GLTF_PT_export_main,
GLTF_PT_export_include,
GLTF_PT_export_transform,
GLTF_PT_export_geometry,
GLTF_PT_export_geometry_compression,
GLTF_PT_export_animation,
GLTF_PT_export_animation_export,
GLTF_PT_export_animation_shapekeys,
GLTF_PT_export_animation_skinning,
GLTF_PT_export_user_extensions,
ImportGLTF2,
GLTF_PT_import_user_extensions
)
def register():
for c in classes:
bpy.utils.register_class(c)
# bpy.utils.register_module(__name__)
# add to the export / import menu
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
def unregister():
for c in classes:
bpy.utils.unregister_class(c)
for f in exporter_extension_panel_unregister_functors:
f()
exporter_extension_panel_unregister_functors.clear()
for f in importer_extension_panel_unregister_functors:
importer_extension_panel_unregister_functors.clear()
# bpy.utils.unregister_module(__name__)
# remove from the export / import menu
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)