1 # Copyright 2018-2019 The glTF-Blender-IO authors.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 'name': 'glTF 2.0 format',
17 'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
18 "version": (1, 1, 46),
19 'blender': (2, 81, 6),
20 'location': 'File > Import-Export',
21 'description': 'Import-Export as glTF 2.0',
23 'wiki_url': "https://docs.blender.org/manual/en/2.82/addons/import_export/io_scene_gltf2.html",
24 'tracker_url': "https://github.com/KhronosGroup/glTF-Blender-IO/issues/",
25 'support': 'OFFICIAL',
26 'category': 'Import-Export',
29 def get_version_string():
30 return str(bl_info
['version'][0]) + '.' + str(bl_info
['version'][1]) + '.' + str(bl_info
['version'][2])
33 # Script reloading (if the user calls 'Reload Scripts' from Blender)
36 def reload_package(module_dict_main
):
38 from pathlib
import Path
40 def reload_package_recursive(current_dir
, module_dict
):
41 for path
in current_dir
.iterdir():
42 if "__init__" in str(path
) or path
.stem
not in module_dict
:
45 if path
.is_file() and path
.suffix
== ".py":
46 importlib
.reload(module_dict
[path
.stem
])
48 reload_package_recursive(path
, module_dict
[path
.stem
].__dict
__)
50 reload_package_recursive(Path(__file__
).parent
, module_dict_main
)
54 reload_package(locals())
57 from bpy
.props
import (StringProperty
,
62 from bpy
.types
import Operator
63 from bpy_extras
.io_utils
import ImportHelper
, ExportHelper
67 # Functions / Classes.
70 extension_panel_unregister_functors
= []
72 class ExportGLTF2_Base
:
73 # TODO: refactor to avoid boilerplate
76 from io_scene_gltf2
.io
.exp
import gltf2_io_draco_compression_extension
77 self
.is_draco_available
= gltf2_io_draco_compression_extension
.dll_exists()
79 bl_options
= {'UNDO', 'PRESET'}
81 export_format
: EnumProperty(
83 items
=(('GLB', 'glTF Binary (.glb)',
84 'Exports a single file, with all data packed in binary form. '
85 'Most efficient and portable, but more difficult to edit later'),
86 ('GLTF_EMBEDDED', 'glTF Embedded (.gltf)',
87 'Exports a single file, with all data packed in JSON. '
88 'Less efficient than binary, but easier to edit later'),
89 ('GLTF_SEPARATE', 'glTF Separate (.gltf + .bin + textures)',
90 'Exports multiple files, with separate JSON, binary and texture data. '
91 'Easiest to edit later')),
93 'Output format and embedding options. Binary is most efficient, '
94 'but JSON (embedded or separate) may be easier to edit later'
100 items
=(('GENERAL', "General", "General settings"),
101 ('MESHES', "Meshes", "Mesh settings"),
102 ('OBJECTS', "Objects", "Object settings"),
103 ('ANIMATION', "Animation", "Animation settings")),
105 description
="Export setting categories",
108 export_copyright
: StringProperty(
110 description
='Legal rights and conditions for the model',
114 export_image_format
: EnumProperty(
116 items
=(('NAME', 'Automatic',
117 'Determine the image format from the blender image name'),
118 ('JPEG', 'JPEG Format (.jpg)',
119 'Encode and save textures as .jpg files. Be aware of a possible loss in quality'),
120 ('PNG', 'PNG Format (.png)',
121 'Encode and save textures as .png files')
124 'Output format for images. PNG is lossless and generally preferred, but JPEG might be preferable for web '
125 'applications due to the smaller file size'
130 export_texture_dir
: StringProperty(
132 description
='Folder to place texture files in. Relative to the .gltf file',
136 export_texcoords
: BoolProperty(
138 description
='Export UVs (texture coordinates) with meshes',
142 export_normals
: BoolProperty(
144 description
='Export vertex normals with meshes',
148 export_draco_mesh_compression_enable
: BoolProperty(
149 name
='Draco mesh compression',
150 description
='Compress mesh using Draco',
154 export_draco_mesh_compression_level
: IntProperty(
155 name
='Compression level',
156 description
='Compression level (0 = most speed, 6 = most compression, higher values currently not supported)',
162 export_draco_position_quantization
: IntProperty(
163 name
='Position quantization bits',
164 description
='Quantization bits for position values (0 = no quantization)',
170 export_draco_normal_quantization
: IntProperty(
171 name
='Normal quantization bits',
172 description
='Quantization bits for normal values (0 = no quantization)',
178 export_draco_texcoord_quantization
: IntProperty(
179 name
='Texcoord quantization bits',
180 description
='Quantization bits for texture coordinate values (0 = no quantization)',
186 export_draco_generic_quantization
: IntProperty(
187 name
='Generic quantization bits',
188 description
='Quantization bits for generic coordinate values like weights or joints (0 = no quantization)',
194 export_tangents
: BoolProperty(
196 description
='Export vertex tangents with meshes',
200 export_materials
: BoolProperty(
202 description
='Export materials',
206 export_colors
: BoolProperty(
207 name
='Vertex Colors',
208 description
='Export vertex colors with meshes',
212 export_cameras
: BoolProperty(
214 description
='Export cameras',
218 export_selected
: BoolProperty(
219 name
='Selected Objects',
220 description
='Export selected objects only',
224 export_extras
: BoolProperty(
225 name
='Custom Properties',
226 description
='Export custom properties as glTF extras',
230 export_yup
: BoolProperty(
232 description
='Export using glTF convention, +Y up',
236 export_apply
: BoolProperty(
237 name
='Apply Modifiers',
238 description
='Apply modifiers (excluding Armatures) to mesh objects -'
239 'WARNING: prevents exporting shape keys',
243 export_animations
: BoolProperty(
245 description
='Exports active actions and NLA tracks as glTF animations',
249 export_frame_range
: BoolProperty(
250 name
='Limit to Playback Range',
251 description
='Clips animations to selected playback range',
255 export_frame_step
: IntProperty(
256 name
='Sampling Rate',
257 description
='How often to evaluate animated values (in frames)',
263 export_force_sampling
: BoolProperty(
264 name
='Always Sample Animations',
265 description
='Apply sampling to all animations',
269 export_nla_strips
: BoolProperty(
271 description
='Export NLA Strip animations',
275 export_def_bones
: BoolProperty(
276 name
='Export Deformation bones only',
277 description
='Export Deformation bones only (and needed bones for hierarchy)',
281 export_current_frame
: BoolProperty(
282 name
='Use Current Frame',
283 description
='Export the scene in the current animation frame',
287 export_skins
: BoolProperty(
289 description
='Export skinning (armature) data',
293 export_all_influences
: BoolProperty(
294 name
='Include All Bone Influences',
295 description
='Allow >4 joint vertex influences. Models may appear incorrectly in many viewers',
299 export_morph
: BoolProperty(
301 description
='Export shape keys (morph targets)',
305 export_morph_normal
: BoolProperty(
306 name
='Shape Key Normals',
307 description
='Export vertex normals with shape keys (morph targets)',
311 export_morph_tangent
: BoolProperty(
312 name
='Shape Key Tangents',
313 description
='Export vertex tangents with shape keys (morph targets)',
317 export_lights
: BoolProperty(
318 name
='Punctual Lights',
319 description
='Export directional, point, and spot lights. '
320 'Uses "KHR_lights_punctual" glTF extension',
324 export_displacement
: BoolProperty(
325 name
='Displacement Textures (EXPERIMENTAL)',
326 description
='EXPERIMENTAL: Export displacement textures. '
327 'Uses incomplete "KHR_materials_displacement" glTF extension',
331 will_save_settings
: BoolProperty(
332 name
='Remember Export Settings',
333 description
='Store glTF export settings in the Blender project',
336 # Custom scene property for saving settings
337 scene_key
= "glTF2ExportSettings"
341 def invoke(self
, context
, event
):
342 settings
= context
.scene
.get(self
.scene_key
)
343 self
.will_save_settings
= False
344 self
.has_active_extenions
= False
347 for (k
, v
) in settings
.items():
349 self
.will_save_settings
= True
351 except (AttributeError, TypeError):
352 self
.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
353 del context
.scene
[self
.scene_key
]
356 preferences
= bpy
.context
.preferences
357 for addon_name
in preferences
.addons
.keys():
359 if hasattr(sys
.modules
[addon_name
], 'glTF2ExportUserExtension') or hasattr(sys
.modules
[addon_name
], 'glTF2ExportUserExtensions'):
360 extension_panel_unregister_functors
.append(sys
.modules
[addon_name
].register_panel())
361 self
.has_active_extenions
= True
365 return ExportHelper
.invoke(self
, context
, event
)
367 def save_settings(self
, context
):
368 # find all export_ props
369 all_props
= self
.properties
370 export_props
= {x
: getattr(self
, x
) for x
in dir(all_props
)
371 if x
.startswith("export_") and all_props
.get(x
) is not None}
373 context
.scene
[self
.scene_key
] = export_props
375 def execute(self
, context
):
378 from .blender
.exp
import gltf2_blender_export
380 if self
.will_save_settings
:
381 self
.save_settings(context
)
383 if self
.export_format
== 'GLB':
384 self
.filename_ext
= '.glb'
386 self
.filename_ext
= '.gltf'
388 # All custom export settings are stored in this container.
391 export_settings
['timestamp'] = datetime
.datetime
.now()
393 export_settings
['gltf_filepath'] = bpy
.path
.ensure_ext(self
.filepath
, self
.filename_ext
)
394 export_settings
['gltf_filedirectory'] = os
.path
.dirname(export_settings
['gltf_filepath']) + '/'
395 export_settings
['gltf_texturedirectory'] = os
.path
.join(
396 export_settings
['gltf_filedirectory'],
397 self
.export_texture_dir
,
400 export_settings
['gltf_format'] = self
.export_format
401 export_settings
['gltf_image_format'] = self
.export_image_format
402 export_settings
['gltf_copyright'] = self
.export_copyright
403 export_settings
['gltf_texcoords'] = self
.export_texcoords
404 export_settings
['gltf_normals'] = self
.export_normals
405 export_settings
['gltf_tangents'] = self
.export_tangents
and self
.export_normals
407 if self
.is_draco_available
:
408 export_settings
['gltf_draco_mesh_compression'] = self
.export_draco_mesh_compression_enable
409 export_settings
['gltf_draco_mesh_compression_level'] = self
.export_draco_mesh_compression_level
410 export_settings
['gltf_draco_position_quantization'] = self
.export_draco_position_quantization
411 export_settings
['gltf_draco_normal_quantization'] = self
.export_draco_normal_quantization
412 export_settings
['gltf_draco_texcoord_quantization'] = self
.export_draco_texcoord_quantization
413 export_settings
['gltf_draco_generic_quantization'] = self
.export_draco_generic_quantization
415 export_settings
['gltf_draco_mesh_compression'] = False
417 export_settings
['gltf_materials'] = self
.export_materials
418 export_settings
['gltf_colors'] = self
.export_colors
419 export_settings
['gltf_cameras'] = self
.export_cameras
420 export_settings
['gltf_selected'] = self
.export_selected
421 export_settings
['gltf_layers'] = True # self.export_layers
422 export_settings
['gltf_extras'] = self
.export_extras
423 export_settings
['gltf_yup'] = self
.export_yup
424 export_settings
['gltf_apply'] = self
.export_apply
425 export_settings
['gltf_current_frame'] = self
.export_current_frame
426 export_settings
['gltf_animations'] = self
.export_animations
427 if self
.export_animations
:
428 export_settings
['gltf_frame_range'] = self
.export_frame_range
429 export_settings
['gltf_force_sampling'] = self
.export_force_sampling
430 if self
.export_force_sampling
:
431 export_settings
['gltf_def_bones'] = self
.export_def_bones
433 export_settings
['gltf_def_bones'] = False
434 export_settings
['gltf_nla_strips'] = self
.export_nla_strips
436 export_settings
['gltf_frame_range'] = False
437 export_settings
['gltf_move_keyframes'] = False
438 export_settings
['gltf_force_sampling'] = False
439 export_settings
['gltf_def_bones'] = False
440 export_settings
['gltf_skins'] = self
.export_skins
441 if self
.export_skins
:
442 export_settings
['gltf_all_vertex_influences'] = self
.export_all_influences
444 export_settings
['gltf_all_vertex_influences'] = False
445 export_settings
['gltf_frame_step'] = self
.export_frame_step
446 export_settings
['gltf_morph'] = self
.export_morph
447 if self
.export_morph
:
448 export_settings
['gltf_morph_normal'] = self
.export_morph_normal
450 export_settings
['gltf_morph_normal'] = False
451 if self
.export_morph
and self
.export_morph_normal
:
452 export_settings
['gltf_morph_tangent'] = self
.export_morph_tangent
454 export_settings
['gltf_morph_tangent'] = False
456 export_settings
['gltf_lights'] = self
.export_lights
457 export_settings
['gltf_displacement'] = self
.export_displacement
459 export_settings
['gltf_binary'] = bytearray()
460 export_settings
['gltf_binaryfilename'] = os
.path
.splitext(os
.path
.basename(
461 bpy
.path
.ensure_ext(self
.filepath
,self
.filename_ext
)))[0] + '.bin'
466 preferences
= bpy
.context
.preferences
467 for addon_name
in preferences
.addons
.keys():
469 module
= sys
.modules
[addon_name
]
472 if hasattr(module
, 'glTF2ExportUserExtension'):
473 extension_ctor
= module
.glTF2ExportUserExtension
474 user_extensions
.append(extension_ctor())
475 if hasattr(module
, 'glTF2ExportUserExtensions'):
476 extension_ctors
= module
.glTF2ExportUserExtensions
477 for extension_ctor
in extension_ctors
:
478 user_extensions
.append(extension_ctor())
479 export_settings
['gltf_user_extensions'] = user_extensions
481 return gltf2_blender_export
.save(context
, export_settings
)
488 def draw(self
, context
):
492 class GLTF_PT_export_main(bpy
.types
.Panel
):
493 bl_space_type
= 'FILE_BROWSER'
494 bl_region_type
= 'TOOL_PROPS'
496 bl_parent_id
= "FILE_PT_operator"
497 bl_options
= {'HIDE_HEADER'}
500 def poll(cls
, context
):
501 sfile
= context
.space_data
502 operator
= sfile
.active_operator
504 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
506 def draw(self
, context
):
508 layout
.use_property_split
= True
509 layout
.use_property_decorate
= False # No animation.
511 sfile
= context
.space_data
512 operator
= sfile
.active_operator
514 layout
.prop(operator
, 'export_format')
515 if operator
.export_format
== 'GLTF_SEPARATE':
516 layout
.prop(operator
, 'export_texture_dir', icon
='FILE_FOLDER')
517 layout
.prop(operator
, 'export_copyright')
518 layout
.prop(operator
, 'will_save_settings')
521 class GLTF_PT_export_include(bpy
.types
.Panel
):
522 bl_space_type
= 'FILE_BROWSER'
523 bl_region_type
= 'TOOL_PROPS'
525 bl_parent_id
= "FILE_PT_operator"
526 bl_options
= {'DEFAULT_CLOSED'}
529 def poll(cls
, context
):
530 sfile
= context
.space_data
531 operator
= sfile
.active_operator
533 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
535 def draw(self
, context
):
537 layout
.use_property_split
= True
538 layout
.use_property_decorate
= False # No animation.
540 sfile
= context
.space_data
541 operator
= sfile
.active_operator
543 layout
.prop(operator
, 'export_selected')
544 layout
.prop(operator
, 'export_extras')
545 layout
.prop(operator
, 'export_cameras')
546 layout
.prop(operator
, 'export_lights')
549 class GLTF_PT_export_transform(bpy
.types
.Panel
):
550 bl_space_type
= 'FILE_BROWSER'
551 bl_region_type
= 'TOOL_PROPS'
552 bl_label
= "Transform"
553 bl_parent_id
= "FILE_PT_operator"
554 bl_options
= {'DEFAULT_CLOSED'}
557 def poll(cls
, context
):
558 sfile
= context
.space_data
559 operator
= sfile
.active_operator
561 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
563 def draw(self
, context
):
565 layout
.use_property_split
= True
566 layout
.use_property_decorate
= False # No animation.
568 sfile
= context
.space_data
569 operator
= sfile
.active_operator
571 layout
.prop(operator
, 'export_yup')
574 class GLTF_PT_export_geometry(bpy
.types
.Panel
):
575 bl_space_type
= 'FILE_BROWSER'
576 bl_region_type
= 'TOOL_PROPS'
577 bl_label
= "Geometry"
578 bl_parent_id
= "FILE_PT_operator"
579 bl_options
= {'DEFAULT_CLOSED'}
582 def poll(cls
, context
):
583 sfile
= context
.space_data
584 operator
= sfile
.active_operator
586 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
588 def draw(self
, context
):
590 layout
.use_property_split
= True
591 layout
.use_property_decorate
= False # No animation.
593 sfile
= context
.space_data
594 operator
= sfile
.active_operator
596 layout
.prop(operator
, 'export_apply')
597 layout
.prop(operator
, 'export_texcoords')
598 layout
.prop(operator
, 'export_normals')
599 col
= layout
.column()
600 col
.active
= operator
.export_normals
601 col
.prop(operator
, 'export_tangents')
602 layout
.prop(operator
, 'export_colors')
603 layout
.prop(operator
, 'export_materials')
604 col
= layout
.column()
605 col
.active
= operator
.export_materials
606 col
.prop(operator
, 'export_image_format')
609 class GLTF_PT_export_geometry_compression(bpy
.types
.Panel
):
610 bl_space_type
= 'FILE_BROWSER'
611 bl_region_type
= 'TOOL_PROPS'
612 bl_label
= "Compression"
613 bl_parent_id
= "GLTF_PT_export_geometry"
614 bl_options
= {'DEFAULT_CLOSED'}
617 from io_scene_gltf2
.io
.exp
import gltf2_io_draco_compression_extension
618 self
.is_draco_available
= gltf2_io_draco_compression_extension
.dll_exists(quiet
=True)
621 def poll(cls
, context
):
622 sfile
= context
.space_data
623 operator
= sfile
.active_operator
624 if operator
.is_draco_available
:
625 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
627 def draw_header(self
, context
):
628 sfile
= context
.space_data
629 operator
= sfile
.active_operator
630 self
.layout
.prop(operator
, "export_draco_mesh_compression_enable", text
="")
632 def draw(self
, context
):
634 layout
.use_property_split
= True
635 layout
.use_property_decorate
= False # No animation.
637 sfile
= context
.space_data
638 operator
= sfile
.active_operator
640 layout
.active
= operator
.export_draco_mesh_compression_enable
641 layout
.prop(operator
, 'export_draco_mesh_compression_level')
643 col
= layout
.column(align
=True)
644 col
.prop(operator
, 'export_draco_position_quantization', text
="Quantize Position")
645 col
.prop(operator
, 'export_draco_normal_quantization', text
="Normal")
646 col
.prop(operator
, 'export_draco_texcoord_quantization', text
="Tex Coords")
647 col
.prop(operator
, 'export_draco_generic_quantization', text
="Generic")
650 class GLTF_PT_export_animation(bpy
.types
.Panel
):
651 bl_space_type
= 'FILE_BROWSER'
652 bl_region_type
= 'TOOL_PROPS'
653 bl_label
= "Animation"
654 bl_parent_id
= "FILE_PT_operator"
655 bl_options
= {'DEFAULT_CLOSED'}
658 def poll(cls
, context
):
659 sfile
= context
.space_data
660 operator
= sfile
.active_operator
662 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
664 def draw(self
, context
):
666 layout
.use_property_split
= True
667 layout
.use_property_decorate
= False # No animation.
669 sfile
= context
.space_data
670 operator
= sfile
.active_operator
672 layout
.prop(operator
, 'export_current_frame')
675 class GLTF_PT_export_animation_export(bpy
.types
.Panel
):
676 bl_space_type
= 'FILE_BROWSER'
677 bl_region_type
= 'TOOL_PROPS'
678 bl_label
= "Animation"
679 bl_parent_id
= "GLTF_PT_export_animation"
680 bl_options
= {'DEFAULT_CLOSED'}
683 def poll(cls
, context
):
684 sfile
= context
.space_data
685 operator
= sfile
.active_operator
687 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
689 def draw_header(self
, context
):
690 sfile
= context
.space_data
691 operator
= sfile
.active_operator
692 self
.layout
.prop(operator
, "export_animations", text
="")
694 def draw(self
, context
):
696 layout
.use_property_split
= True
697 layout
.use_property_decorate
= False # No animation.
699 sfile
= context
.space_data
700 operator
= sfile
.active_operator
702 layout
.active
= operator
.export_animations
704 layout
.prop(operator
, 'export_frame_range')
705 layout
.prop(operator
, 'export_frame_step')
706 layout
.prop(operator
, 'export_force_sampling')
707 layout
.prop(operator
, 'export_nla_strips')
710 row
.active
= operator
.export_force_sampling
711 row
.prop(operator
, 'export_def_bones')
714 class GLTF_PT_export_animation_shapekeys(bpy
.types
.Panel
):
715 bl_space_type
= 'FILE_BROWSER'
716 bl_region_type
= 'TOOL_PROPS'
717 bl_label
= "Shape Keys"
718 bl_parent_id
= "GLTF_PT_export_animation"
719 bl_options
= {'DEFAULT_CLOSED'}
722 def poll(cls
, context
):
723 sfile
= context
.space_data
724 operator
= sfile
.active_operator
726 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
728 def draw_header(self
, context
):
729 sfile
= context
.space_data
730 operator
= sfile
.active_operator
731 self
.layout
.prop(operator
, "export_morph", text
="")
733 def draw(self
, context
):
735 layout
.use_property_split
= True
736 layout
.use_property_decorate
= False # No animation.
738 sfile
= context
.space_data
739 operator
= sfile
.active_operator
741 layout
.active
= operator
.export_morph
743 layout
.prop(operator
, 'export_morph_normal')
744 col
= layout
.column()
745 col
.active
= operator
.export_morph_normal
746 col
.prop(operator
, 'export_morph_tangent')
749 class GLTF_PT_export_animation_skinning(bpy
.types
.Panel
):
750 bl_space_type
= 'FILE_BROWSER'
751 bl_region_type
= 'TOOL_PROPS'
752 bl_label
= "Skinning"
753 bl_parent_id
= "GLTF_PT_export_animation"
754 bl_options
= {'DEFAULT_CLOSED'}
757 def poll(cls
, context
):
758 sfile
= context
.space_data
759 operator
= sfile
.active_operator
761 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
763 def draw_header(self
, context
):
764 sfile
= context
.space_data
765 operator
= sfile
.active_operator
766 self
.layout
.prop(operator
, "export_skins", text
="")
768 def draw(self
, context
):
770 layout
.use_property_split
= True
771 layout
.use_property_decorate
= False # No animation.
773 sfile
= context
.space_data
774 operator
= sfile
.active_operator
776 layout
.active
= operator
.export_skins
777 layout
.prop(operator
, 'export_all_influences')
779 class GLTF_PT_export_user_extensions(bpy
.types
.Panel
):
780 bl_space_type
= 'FILE_BROWSER'
781 bl_region_type
= 'TOOL_PROPS'
782 bl_label
= "Extensions"
783 bl_parent_id
= "FILE_PT_operator"
784 bl_options
= {'DEFAULT_CLOSED'}
787 def poll(cls
, context
):
788 sfile
= context
.space_data
789 operator
= sfile
.active_operator
791 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf" and operator
.has_active_extenions
793 def draw(self
, context
):
795 layout
.use_property_split
= True
796 layout
.use_property_decorate
= False # No animation.
799 class ExportGLTF2(bpy
.types
.Operator
, ExportGLTF2_Base
, ExportHelper
):
800 """Export scene as glTF 2.0 file"""
801 bl_idname
= 'export_scene.gltf'
802 bl_label
= 'Export glTF 2.0'
806 filter_glob
: StringProperty(default
='*.glb;*.gltf', options
={'HIDDEN'})
809 def menu_func_export(self
, context
):
810 self
.layout
.operator(ExportGLTF2
.bl_idname
, text
='glTF 2.0 (.glb/.gltf)')
813 class ImportGLTF2(Operator
, ImportHelper
):
814 """Load a glTF 2.0 file"""
815 bl_idname
= 'import_scene.gltf'
816 bl_label
= 'Import glTF 2.0'
818 filter_glob
: StringProperty(default
="*.glb;*.gltf", options
={'HIDDEN'})
820 files
: CollectionProperty(
822 type=bpy
.types
.OperatorFileListElement
,
825 loglevel
: IntProperty(
827 description
="Log Level")
829 import_pack_images
: BoolProperty(
831 description
='Pack all images into .blend file',
835 import_shading
: EnumProperty(
837 items
=(("NORMALS", "Use Normal Data", ""),
838 ("FLAT", "Flat Shading", ""),
839 ("SMOOTH", "Smooth Shading", "")),
840 description
="How normals are computed during import",
843 def draw(self
, context
):
846 layout
.prop(self
, 'import_pack_images')
847 layout
.prop(self
, 'import_shading')
849 def execute(self
, context
):
850 return self
.import_gltf2(context
)
852 def import_gltf2(self
, context
):
856 import_settings
= self
.as_keywords()
859 # Multiple file import
861 dirname
= os
.path
.dirname(self
.filepath
)
862 for file in self
.files
:
863 path
= os
.path
.join(dirname
, file.name
)
864 if self
.unit_import(path
, import_settings
) == {'FINISHED'}:
869 return self
.unit_import(self
.filepath
, import_settings
)
871 def unit_import(self
, filename
, import_settings
):
873 from .io
.imp
.gltf2_io_gltf
import glTFImporter
874 from .blender
.imp
.gltf2_blender_gltf
import BlenderGlTF
876 self
.gltf_importer
= glTFImporter(filename
, import_settings
)
877 success
, txt
= self
.gltf_importer
.read()
879 self
.report({'ERROR'}, txt
)
881 success
, txt
= self
.gltf_importer
.checks()
883 self
.report({'ERROR'}, txt
)
885 self
.gltf_importer
.log
.critical("Data are loaded, start creating Blender stuff")
886 start_time
= time
.time()
887 BlenderGlTF
.create(self
.gltf_importer
)
888 elapsed_s
= "{:.2f}s".format(time
.time() - start_time
)
889 self
.gltf_importer
.log
.critical("glTF import finished in " + elapsed_s
)
890 self
.gltf_importer
.log
.removeHandler(self
.gltf_importer
.log_handler
)
894 def set_debug_log(self
):
896 if bpy
.app
.debug_value
== 0:
897 self
.loglevel
= logging
.CRITICAL
898 elif bpy
.app
.debug_value
== 1:
899 self
.loglevel
= logging
.ERROR
900 elif bpy
.app
.debug_value
== 2:
901 self
.loglevel
= logging
.WARNING
902 elif bpy
.app
.debug_value
== 3:
903 self
.loglevel
= logging
.INFO
905 self
.loglevel
= logging
.NOTSET
908 def menu_func_import(self
, context
):
909 self
.layout
.operator(ImportGLTF2
.bl_idname
, text
='glTF 2.0 (.glb/.gltf)')
915 GLTF_PT_export_include
,
916 GLTF_PT_export_transform
,
917 GLTF_PT_export_geometry
,
918 GLTF_PT_export_geometry_compression
,
919 GLTF_PT_export_animation
,
920 GLTF_PT_export_animation_export
,
921 GLTF_PT_export_animation_shapekeys
,
922 GLTF_PT_export_animation_skinning
,
923 GLTF_PT_export_user_extensions
,
930 bpy
.utils
.register_class(c
)
931 # bpy.utils.register_module(__name__)
933 # add to the export / import menu
934 bpy
.types
.TOPBAR_MT_file_export
.append(menu_func_export
)
935 bpy
.types
.TOPBAR_MT_file_import
.append(menu_func_import
)
940 bpy
.utils
.unregister_class(c
)
941 for f
in extension_panel_unregister_functors
:
943 extension_panel_unregister_functors
.clear()
945 # bpy.utils.unregister_module(__name__)
947 # remove from the export / import menu
948 bpy
.types
.TOPBAR_MT_file_export
.remove(menu_func_export
)
949 bpy
.types
.TOPBAR_MT_file_import
.remove(menu_func_import
)