1 # SPDX-License-Identifier: Apache-2.0
2 # Copyright 2018-2021 The glTF-Blender-IO authors.
5 'name': 'glTF 2.0 format',
6 'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
9 'location': 'File > Import-Export',
10 'description': 'Import-Export as glTF 2.0',
12 'doc_url': "{BLENDER_MANUAL_URL}/addons/import_export/scene_gltf2.html",
13 'tracker_url': "https://github.com/KhronosGroup/glTF-Blender-IO/issues/",
14 'support': 'OFFICIAL',
15 'category': 'Import-Export',
18 def get_version_string():
19 return str(bl_info
['version'][0]) + '.' + str(bl_info
['version'][1]) + '.' + str(bl_info
['version'][2])
22 # Script reloading (if the user calls 'Reload Scripts' from Blender)
25 def reload_package(module_dict_main
):
27 from pathlib
import Path
29 def reload_package_recursive(current_dir
, module_dict
):
30 for path
in current_dir
.iterdir():
31 if "__init__" in str(path
) or path
.stem
not in module_dict
:
34 if path
.is_file() and path
.suffix
== ".py":
35 importlib
.reload(module_dict
[path
.stem
])
37 reload_package_recursive(path
, module_dict
[path
.stem
].__dict
__)
39 reload_package_recursive(Path(__file__
).parent
, module_dict_main
)
43 reload_package(locals())
46 from bpy
.props
import (StringProperty
,
51 from bpy
.types
import Operator
52 from bpy_extras
.io_utils
import ImportHelper
, ExportHelper
56 # Functions / Classes.
59 exporter_extension_panel_unregister_functors
= []
60 importer_extension_panel_unregister_functors
= []
63 def ensure_filepath_matches_export_format(filepath
, export_format
):
65 filename
= os
.path
.basename(filepath
)
69 stem
, ext
= os
.path
.splitext(filename
)
70 if stem
.startswith('.') and not ext
:
73 desired_ext
= '.glb' if export_format
== 'GLB' else '.gltf'
74 ext_lower
= ext
.lower()
75 if ext_lower
not in ['.glb', '.gltf']:
76 return filepath
+ desired_ext
77 elif ext_lower
!= desired_ext
:
78 filepath
= filepath
[:-len(ext
)] # strip off ext
79 return filepath
+ desired_ext
84 def on_export_format_changed(self
, context
):
85 # Update the filename in the file browser when the format (.glb/.gltf)
87 sfile
= context
.space_data
88 if not isinstance(sfile
, bpy
.types
.SpaceFileBrowser
):
90 if not sfile
.active_operator
:
92 if sfile
.active_operator
.bl_idname
!= "EXPORT_SCENE_OT_gltf":
95 sfile
.params
.filename
= ensure_filepath_matches_export_format(
96 sfile
.params
.filename
,
100 # Also change the filter
101 sfile
.params
.filter_glob
= '*.glb' if self
.export_format
== 'GLB' else '*.gltf'
102 # Force update of file list, has update the filter does not update the real file list
103 bpy
.ops
.file.refresh()
106 class ConvertGLTF2_Base
:
107 """Base class containing options that should be exposed during both import and export."""
109 export_import_convert_lighting_mode
: EnumProperty(
110 name
='Lighting Mode',
112 ('SPEC', 'Standard', 'Physically-based glTF lighting units (cd, lx, nt)'),
113 ('COMPAT', 'Unitless', 'Non-physical, unitless lighting. Useful when exposure controls are not available'),
114 ('RAW', 'Raw (Deprecated)', 'Blender lighting strengths with no conversion'),
116 description
='Optional backwards compatibility for non-standard render engines. Applies to lights',# TODO: and emissive materials',
120 class ExportGLTF2_Base(ConvertGLTF2_Base
):
121 # TODO: refactor to avoid boilerplate
124 from .io
.com
import gltf2_io_draco_compression_extension
125 self
.is_draco_available
= gltf2_io_draco_compression_extension
.dll_exists()
127 bl_options
= {'PRESET'}
129 # Don't use export_ prefix here, I don't want it to be saved with other export settings
130 gltf_export_id
: StringProperty(
133 'Identifier of caller (in case of add-on calling this exporter). '
134 'Can be useful in case of Extension added by other add-ons'
139 export_format
: EnumProperty(
141 items
=(('GLB', 'glTF Binary (.glb)',
142 'Exports a single file, with all data packed in binary form. '
143 'Most efficient and portable, but more difficult to edit later'),
144 ('GLTF_SEPARATE', 'glTF Separate (.gltf + .bin + textures)',
145 'Exports multiple files, with separate JSON, binary and texture data. '
146 'Easiest to edit later'),
147 ('GLTF_EMBEDDED', 'glTF Embedded (.gltf)',
148 'Exports a single file, with all data packed in JSON. '
149 'Less efficient than binary, but easier to edit later')),
151 'Output format and embedding options. Binary is most efficient, '
152 'but JSON (embedded or separate) may be easier to edit later'
154 default
='GLB', #Warning => If you change the default, need to change the default filter too
155 update
=on_export_format_changed
,
158 ui_tab
: EnumProperty(
159 items
=(('GENERAL', "General", "General settings"),
160 ('MESHES', "Meshes", "Mesh settings"),
161 ('OBJECTS', "Objects", "Object settings"),
162 ('ANIMATION', "Animation", "Animation settings")),
164 description
="Export setting categories",
167 export_copyright
: StringProperty(
169 description
='Legal rights and conditions for the model',
173 export_image_format
: EnumProperty(
175 items
=(('AUTO', 'Automatic',
176 'Save PNGs as PNGs and JPEGs as JPEGs. '
177 'If neither one, use PNG'),
178 ('JPEG', 'JPEG Format (.jpg)',
179 'Save images as JPEGs. (Images that need alpha are saved as PNGs though.) '
180 'Be aware of a possible loss in quality'),
182 'Don\'t export images'),
185 'Output format for images. PNG is lossless and generally preferred, but JPEG might be preferable for web '
186 'applications due to the smaller file size. Alternatively they can be omitted if they are not needed'
191 export_texture_dir
: StringProperty(
193 description
='Folder to place texture files in. Relative to the .gltf file',
197 export_jpeg_quality
: IntProperty(
199 description
='Quality of JPEG export',
205 export_keep_originals
: BoolProperty(
206 name
='Keep original',
207 description
=('Keep original textures files if possible. '
208 'WARNING: if you use more than one texture, '
209 'where pbr standard requires only one, only one texture will be used. '
210 'This can lead to unexpected results'
215 export_texcoords
: BoolProperty(
217 description
='Export UVs (texture coordinates) with meshes',
221 export_normals
: BoolProperty(
223 description
='Export vertex normals with meshes',
227 export_draco_mesh_compression_enable
: BoolProperty(
228 name
='Draco mesh compression',
229 description
='Compress mesh using Draco',
233 export_draco_mesh_compression_level
: IntProperty(
234 name
='Compression level',
235 description
='Compression level (0 = most speed, 6 = most compression, higher values currently not supported)',
241 export_draco_position_quantization
: IntProperty(
242 name
='Position quantization bits',
243 description
='Quantization bits for position values (0 = no quantization)',
249 export_draco_normal_quantization
: IntProperty(
250 name
='Normal quantization bits',
251 description
='Quantization bits for normal values (0 = no quantization)',
257 export_draco_texcoord_quantization
: IntProperty(
258 name
='Texcoord quantization bits',
259 description
='Quantization bits for texture coordinate values (0 = no quantization)',
265 export_draco_color_quantization
: IntProperty(
266 name
='Color quantization bits',
267 description
='Quantization bits for color values (0 = no quantization)',
273 export_draco_generic_quantization
: IntProperty(
274 name
='Generic quantization bits',
275 description
='Quantization bits for generic values like weights or joints (0 = no quantization)',
281 export_tangents
: BoolProperty(
283 description
='Export vertex tangents with meshes',
287 export_materials
: EnumProperty(
289 items
=(('EXPORT', 'Export',
290 'Export all materials used by included objects'),
291 ('PLACEHOLDER', 'Placeholder',
292 'Do not export materials, but write multiple primitive groups per mesh, keeping material slot information'),
293 ('NONE', 'No export',
294 'Do not export materials, and combine mesh primitive groups, losing material slot information')),
295 description
='Export materials',
299 export_original_specular
: BoolProperty(
300 name
='Export original PBR Specular',
302 'Export original glTF PBR Specular, instead of Blender Principled Shader Specular'
307 export_colors
: BoolProperty(
308 name
='Vertex Colors',
309 description
='Export vertex colors with meshes',
313 export_attributes
: BoolProperty(
315 description
='Export Attributes (when starting with underscore)',
319 use_mesh_edges
: BoolProperty(
322 'Export loose edges as lines, using the material from the first material slot'
327 use_mesh_vertices
: BoolProperty(
330 'Export loose points as glTF points, using the material from the first material slot'
335 export_cameras
: BoolProperty(
337 description
='Export cameras',
341 use_selection
: BoolProperty(
342 name
='Selected Objects',
343 description
='Export selected objects only',
347 use_visible
: BoolProperty(
348 name
='Visible Objects',
349 description
='Export visible objects only',
353 use_renderable
: BoolProperty(
354 name
='Renderable Objects',
355 description
='Export renderable objects only',
359 use_active_collection_with_nested
: BoolProperty(
360 name
='Include Nested Collections',
361 description
='Include active collection and nested collections',
365 use_active_collection
: BoolProperty(
366 name
='Active Collection',
367 description
='Export objects in the active collection only',
371 use_active_scene
: BoolProperty(
373 description
='Export active scene only',
377 export_extras
: BoolProperty(
378 name
='Custom Properties',
379 description
='Export custom properties as glTF extras',
383 export_yup
: BoolProperty(
385 description
='Export using glTF convention, +Y up',
389 export_apply
: BoolProperty(
390 name
='Apply Modifiers',
391 description
='Apply modifiers (excluding Armatures) to mesh objects -'
392 'WARNING: prevents exporting shape keys',
396 export_animations
: BoolProperty(
398 description
='Exports active actions and NLA tracks as glTF animations',
402 export_frame_range
: BoolProperty(
403 name
='Limit to Playback Range',
404 description
='Clips animations to selected playback range',
408 export_frame_step
: IntProperty(
409 name
='Sampling Rate',
410 description
='How often to evaluate animated values (in frames)',
416 export_force_sampling
: BoolProperty(
417 name
='Always Sample Animations',
418 description
='Apply sampling to all animations',
422 export_animation_mode
: EnumProperty(
423 name
='Animation mode',
424 items
=(('ACTIONS', 'Actions',
425 'Export actions (actives and on NLA tracks) as separate animations'),
426 ('ACTIVE_ACTIONS', 'Active actions merged',
427 'All the currently assigned actions become one glTF animation'),
428 ('NLA_TRACKS', 'NLA Tracks',
429 'Export individual NLA Tracks as separate animation'),
431 'Export baked scene as a single animation')
433 description
='Export Animation mode',
437 export_nla_strips_merged_animation_name
: StringProperty(
438 name
='Merged Animation Name',
440 "Name of single glTF animation to be exported"
445 export_def_bones
: BoolProperty(
446 name
='Export Deformation Bones Only',
447 description
='Export Deformation bones only',
451 export_hierarchy_flatten_bones
: BoolProperty(
452 name
='Flatten Bone Hierarchy',
453 description
='Flatten Bone Hierarchy. Useful in case of non decomposable transformation matrix',
457 export_optimize_animation_size
: BoolProperty(
458 name
='Optimize Animation Size',
460 "Reduce exported file size by removing duplicate keyframes"
465 export_optimize_animation_keep_anim_armature
: BoolProperty(
466 name
='Force keeping channels for bones',
468 "if all keyframes are identical in a rig, "
469 "force keeping the minimal animation. "
470 "When off, all possible channels for "
471 "the bones will be exported, even if empty "
472 "(minimal animation, 2 keyframes)"
477 export_optimize_animation_keep_anim_object
: BoolProperty(
478 name
='Force keeping channel for objects',
480 "If all keyframes are identical for object transformations, "
481 "force keeping the minimal animation"
486 export_negative_frame
: EnumProperty(
487 name
='Negative Frames',
488 items
=(('SLIDE', 'Slide',
489 'Slide animation to start at frame 0'),
491 'Keep only frames above frame 0'),
493 description
='Negative Frames are slid or cropped',
497 export_anim_slide_to_zero
: BoolProperty(
498 name
='Set all glTF Animation starting at 0',
500 "Set all glTF animation starting at 0.0s. "
501 "Can be useful for looping animations"
506 export_bake_animation
: BoolProperty(
507 name
='Bake All Objects Animations',
509 "Force exporting animation on every objects. "
510 "Can be useful when using constraints or driver. "
511 "Also useful when exporting only selection"
516 export_anim_single_armature
: BoolProperty(
517 name
='Export all Armature Actions',
519 "Export all actions, bound to a single armature. "
520 "WARNING: Option does not support exports including multiple armatures"
525 export_reset_pose_bones
: BoolProperty(
526 name
='Reset pose bones between actions',
528 "Reset pose bones between each action exported. "
529 "This is needed when some bones are not keyed on some animations"
534 export_current_frame
: BoolProperty(
535 name
='Use Current Frame as Object Rest Transformations',
537 'Export the scene in the current animation frame. '
538 'When off, frame O is used as rest transformations for objects'
543 export_rest_position_armature
: BoolProperty(
544 name
='Use Rest Position Armature',
546 "Export armatures using rest position as joins rest pose. "
547 "When off, current frame pose is used as rest pose"
552 export_anim_scene_split_object
: BoolProperty(
553 name
='Split Animation by Object',
555 "Export Scene as seen in Viewport, "
556 "But split animation by Object"
561 export_skins
: BoolProperty(
563 description
='Export skinning (armature) data',
567 export_all_influences
: BoolProperty(
568 name
='Include All Bone Influences',
569 description
='Allow >4 joint vertex influences. Models may appear incorrectly in many viewers',
573 export_morph
: BoolProperty(
575 description
='Export shape keys (morph targets)',
579 export_morph_normal
: BoolProperty(
580 name
='Shape Key Normals',
581 description
='Export vertex normals with shape keys (morph targets)',
585 export_morph_tangent
: BoolProperty(
586 name
='Shape Key Tangents',
587 description
='Export vertex tangents with shape keys (morph targets)',
591 export_morph_animation
: BoolProperty(
592 name
='Shape Key Animations',
593 description
='Export shape keys animations (morph targets)',
597 export_lights
: BoolProperty(
598 name
='Punctual Lights',
599 description
='Export directional, point, and spot lights. '
600 'Uses "KHR_lights_punctual" glTF extension',
604 will_save_settings
: BoolProperty(
605 name
='Remember Export Settings',
606 description
='Store glTF export settings in the Blender project',
609 # Custom scene property for saving settings
610 scene_key
= "glTF2ExportSettings"
614 def check(self
, _context
):
615 # Ensure file extension matches format
616 old_filepath
= self
.filepath
617 self
.filepath
= ensure_filepath_matches_export_format(
621 return self
.filepath
!= old_filepath
623 def invoke(self
, context
, event
):
624 settings
= context
.scene
.get(self
.scene_key
)
625 self
.will_save_settings
= False
628 for (k
, v
) in settings
.items():
630 self
.will_save_settings
= True
632 except (AttributeError, TypeError):
633 self
.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
634 del context
.scene
[self
.scene_key
]
637 preferences
= bpy
.context
.preferences
638 for addon_name
in preferences
.addons
.keys():
640 if hasattr(sys
.modules
[addon_name
], 'glTF2ExportUserExtension') or hasattr(sys
.modules
[addon_name
], 'glTF2ExportUserExtensions'):
641 exporter_extension_panel_unregister_functors
.append(sys
.modules
[addon_name
].register_panel())
645 self
.has_active_exporter_extensions
= len(exporter_extension_panel_unregister_functors
) > 0
646 return ExportHelper
.invoke(self
, context
, event
)
648 def save_settings(self
, context
):
649 # find all props to save
651 # options that don't start with 'export_'
655 'use_active_collection_with_nested',
656 'use_active_collection',
661 all_props
= self
.properties
663 x
: getattr(self
, x
) for x
in dir(all_props
)
664 if (x
.startswith("export_") or x
in exceptional
) and all_props
.get(x
) is not None
666 context
.scene
[self
.scene_key
] = export_props
668 def execute(self
, context
):
671 from .blender
.exp
import gltf2_blender_export
672 from .io
.com
.gltf2_io_path
import path_to_uri
674 if self
.will_save_settings
:
675 self
.save_settings(context
)
677 self
.check(context
) # ensure filepath has the right extension
679 # All custom export settings are stored in this container.
682 export_settings
['timestamp'] = datetime
.datetime
.now()
683 export_settings
['gltf_export_id'] = self
.gltf_export_id
684 export_settings
['gltf_filepath'] = self
.filepath
685 export_settings
['gltf_filedirectory'] = os
.path
.dirname(export_settings
['gltf_filepath']) + '/'
686 export_settings
['gltf_texturedirectory'] = os
.path
.join(
687 export_settings
['gltf_filedirectory'],
688 self
.export_texture_dir
,
690 export_settings
['gltf_keep_original_textures'] = self
.export_keep_originals
692 export_settings
['gltf_format'] = self
.export_format
693 export_settings
['gltf_image_format'] = self
.export_image_format
694 export_settings
['gltf_jpeg_quality'] = self
.export_jpeg_quality
695 export_settings
['gltf_copyright'] = self
.export_copyright
696 export_settings
['gltf_texcoords'] = self
.export_texcoords
697 export_settings
['gltf_normals'] = self
.export_normals
698 export_settings
['gltf_tangents'] = self
.export_tangents
and self
.export_normals
699 export_settings
['gltf_loose_edges'] = self
.use_mesh_edges
700 export_settings
['gltf_loose_points'] = self
.use_mesh_vertices
702 if self
.is_draco_available
:
703 export_settings
['gltf_draco_mesh_compression'] = self
.export_draco_mesh_compression_enable
704 export_settings
['gltf_draco_mesh_compression_level'] = self
.export_draco_mesh_compression_level
705 export_settings
['gltf_draco_position_quantization'] = self
.export_draco_position_quantization
706 export_settings
['gltf_draco_normal_quantization'] = self
.export_draco_normal_quantization
707 export_settings
['gltf_draco_texcoord_quantization'] = self
.export_draco_texcoord_quantization
708 export_settings
['gltf_draco_color_quantization'] = self
.export_draco_color_quantization
709 export_settings
['gltf_draco_generic_quantization'] = self
.export_draco_generic_quantization
711 export_settings
['gltf_draco_mesh_compression'] = False
713 export_settings
['gltf_materials'] = self
.export_materials
714 export_settings
['gltf_colors'] = self
.export_colors
715 export_settings
['gltf_attributes'] = self
.export_attributes
716 export_settings
['gltf_cameras'] = self
.export_cameras
718 export_settings
['gltf_original_specular'] = self
.export_original_specular
720 export_settings
['gltf_visible'] = self
.use_visible
721 export_settings
['gltf_renderable'] = self
.use_renderable
723 export_settings
['gltf_active_collection'] = self
.use_active_collection
724 if self
.use_active_collection
:
725 export_settings
['gltf_active_collection_with_nested'] = self
.use_active_collection_with_nested
727 export_settings
['gltf_active_collection_with_nested'] = False
728 export_settings
['gltf_active_scene'] = self
.use_active_scene
730 export_settings
['gltf_selected'] = self
.use_selection
731 export_settings
['gltf_layers'] = True # self.export_layers
732 export_settings
['gltf_extras'] = self
.export_extras
733 export_settings
['gltf_yup'] = self
.export_yup
734 export_settings
['gltf_apply'] = self
.export_apply
735 export_settings
['gltf_current_frame'] = self
.export_current_frame
736 export_settings
['gltf_animations'] = self
.export_animations
737 export_settings
['gltf_def_bones'] = self
.export_def_bones
738 export_settings
['gltf_flatten_bones_hierarchy'] = self
.export_hierarchy_flatten_bones
739 if self
.export_animations
:
740 export_settings
['gltf_frame_range'] = self
.export_frame_range
741 export_settings
['gltf_force_sampling'] = self
.export_force_sampling
742 if not self
.export_force_sampling
:
743 export_settings
['gltf_def_bones'] = False
744 export_settings
['gltf_bake_animation'] = False
745 export_settings
['gltf_animation_mode'] = self
.export_animation_mode
746 if export_settings
['gltf_animation_mode'] == "NLA_TRACKS":
747 export_settings
['gltf_force_sampling'] = True
748 if export_settings
['gltf_animation_mode'] == "SCENE":
749 export_settings
['gltf_anim_scene_split_object'] = self
.export_anim_scene_split_object
751 export_settings
['gltf_anim_scene_split_object'] = False
753 export_settings
['gltf_nla_strips_merged_animation_name'] = self
.export_nla_strips_merged_animation_name
754 export_settings
['gltf_optimize_animation'] = self
.export_optimize_animation_size
755 export_settings
['gltf_optimize_animation_keep_armature'] = self
.export_optimize_animation_keep_anim_armature
756 export_settings
['gltf_optimize_animation_keep_object'] = self
.export_optimize_animation_keep_anim_object
757 export_settings
['gltf_export_anim_single_armature'] = self
.export_anim_single_armature
758 export_settings
['gltf_export_reset_pose_bones'] = self
.export_reset_pose_bones
759 export_settings
['gltf_bake_animation'] = self
.export_bake_animation
760 export_settings
['gltf_negative_frames'] = self
.export_negative_frame
761 export_settings
['gltf_anim_slide_to_zero'] = self
.export_anim_slide_to_zero
763 export_settings
['gltf_frame_range'] = False
764 export_settings
['gltf_force_sampling'] = False
765 export_settings
['gltf_bake_animation'] = False
766 export_settings
['gltf_optimize_animation'] = False
767 export_settings
['gltf_optimize_animation_keep_armature'] = False
768 export_settings
['gltf_optimize_animation_keep_object'] = False
769 export_settings
['gltf_export_anim_single_armature'] = False
770 export_settings
['gltf_export_reset_pose_bones'] = False
771 export_settings
['gltf_skins'] = self
.export_skins
772 if self
.export_skins
:
773 export_settings
['gltf_all_vertex_influences'] = self
.export_all_influences
775 export_settings
['gltf_all_vertex_influences'] = False
776 export_settings
['gltf_def_bones'] = False
777 export_settings
['gltf_rest_position_armature'] = self
.export_rest_position_armature
778 export_settings
['gltf_frame_step'] = self
.export_frame_step
780 export_settings
['gltf_morph'] = self
.export_morph
781 if self
.export_morph
:
782 export_settings
['gltf_morph_normal'] = self
.export_morph_normal
783 export_settings
['gltf_morph_tangent'] = self
.export_morph_tangent
784 export_settings
['gltf_morph_anim'] = self
.export_morph_animation
786 export_settings
['gltf_morph_normal'] = False
787 export_settings
['gltf_morph_tangent'] = False
788 export_settings
['gltf_morph_anim'] = False
790 export_settings
['gltf_lights'] = self
.export_lights
791 export_settings
['gltf_lighting_mode'] = self
.export_import_convert_lighting_mode
793 export_settings
['gltf_binary'] = bytearray()
794 export_settings
['gltf_binaryfilename'] = (
795 path_to_uri(os
.path
.splitext(os
.path
.basename(self
.filepath
))[0] + '.bin')
799 pre_export_callbacks
= []
800 post_export_callbacks
= []
803 preferences
= bpy
.context
.preferences
804 for addon_name
in preferences
.addons
.keys():
806 module
= sys
.modules
[addon_name
]
809 if hasattr(module
, 'glTF2ExportUserExtension'):
810 extension_ctor
= module
.glTF2ExportUserExtension
811 user_extensions
.append(extension_ctor())
812 if hasattr(module
, 'glTF2ExportUserExtensions'):
813 extension_ctors
= module
.glTF2ExportUserExtensions
814 for extension_ctor
in extension_ctors
:
815 user_extensions
.append(extension_ctor())
816 if hasattr(module
, 'glTF2_pre_export_callback'):
817 pre_export_callbacks
.append(module
.glTF2_pre_export_callback
)
818 if hasattr(module
, 'glTF2_post_export_callback'):
819 post_export_callbacks
.append(module
.glTF2_post_export_callback
)
820 export_settings
['gltf_user_extensions'] = user_extensions
821 export_settings
['pre_export_callbacks'] = pre_export_callbacks
822 export_settings
['post_export_callbacks'] = post_export_callbacks
824 return gltf2_blender_export
.save(context
, export_settings
)
826 def draw(self
, context
):
827 pass # Is needed to get panels available
830 class GLTF_PT_export_main(bpy
.types
.Panel
):
831 bl_space_type
= 'FILE_BROWSER'
832 bl_region_type
= 'TOOL_PROPS'
834 bl_parent_id
= "FILE_PT_operator"
835 bl_options
= {'HIDE_HEADER'}
838 def poll(cls
, context
):
839 sfile
= context
.space_data
840 operator
= sfile
.active_operator
842 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
844 def draw(self
, context
):
846 layout
.use_property_split
= True
847 layout
.use_property_decorate
= False # No animation.
849 sfile
= context
.space_data
850 operator
= sfile
.active_operator
852 layout
.prop(operator
, 'export_format')
853 if operator
.export_format
== 'GLTF_SEPARATE':
854 layout
.prop(operator
, 'export_keep_originals')
855 if operator
.export_keep_originals
is False:
856 layout
.prop(operator
, 'export_texture_dir', icon
='FILE_FOLDER')
858 layout
.prop(operator
, 'export_copyright')
859 layout
.prop(operator
, 'will_save_settings')
862 class GLTF_PT_export_include(bpy
.types
.Panel
):
863 bl_space_type
= 'FILE_BROWSER'
864 bl_region_type
= 'TOOL_PROPS'
866 bl_parent_id
= "FILE_PT_operator"
867 bl_options
= {'DEFAULT_CLOSED'}
870 def poll(cls
, context
):
871 sfile
= context
.space_data
872 operator
= sfile
.active_operator
874 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
876 def draw(self
, context
):
878 layout
.use_property_split
= True
879 layout
.use_property_decorate
= False # No animation.
881 sfile
= context
.space_data
882 operator
= sfile
.active_operator
884 col
= layout
.column(heading
= "Limit to", align
= True)
885 col
.prop(operator
, 'use_selection')
886 col
.prop(operator
, 'use_visible')
887 col
.prop(operator
, 'use_renderable')
888 col
.prop(operator
, 'use_active_collection')
889 if operator
.use_active_collection
:
890 col
.prop(operator
, 'use_active_collection_with_nested')
891 col
.prop(operator
, 'use_active_scene')
893 col
= layout
.column(heading
= "Data", align
= True)
894 col
.prop(operator
, 'export_extras')
895 col
.prop(operator
, 'export_cameras')
896 col
.prop(operator
, 'export_lights')
899 class GLTF_PT_export_transform(bpy
.types
.Panel
):
900 bl_space_type
= 'FILE_BROWSER'
901 bl_region_type
= 'TOOL_PROPS'
902 bl_label
= "Transform"
903 bl_parent_id
= "FILE_PT_operator"
904 bl_options
= {'DEFAULT_CLOSED'}
907 def poll(cls
, context
):
908 sfile
= context
.space_data
909 operator
= sfile
.active_operator
911 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
913 def draw(self
, context
):
915 layout
.use_property_split
= True
916 layout
.use_property_decorate
= False # No animation.
918 sfile
= context
.space_data
919 operator
= sfile
.active_operator
921 layout
.prop(operator
, 'export_yup')
924 class GLTF_PT_export_data(bpy
.types
.Panel
):
925 bl_space_type
= 'FILE_BROWSER'
926 bl_region_type
= 'TOOL_PROPS'
928 bl_parent_id
= "FILE_PT_operator"
929 bl_options
= {'DEFAULT_CLOSED'}
932 def poll(cls
, context
):
933 sfile
= context
.space_data
934 operator
= sfile
.active_operator
936 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
938 def draw(self
, context
):
941 class GLTF_PT_export_data_mesh(bpy
.types
.Panel
):
942 bl_space_type
= 'FILE_BROWSER'
943 bl_region_type
= 'TOOL_PROPS'
945 bl_parent_id
= "GLTF_PT_export_data"
946 bl_options
= {'DEFAULT_CLOSED'}
949 def poll(cls
, context
):
950 sfile
= context
.space_data
951 operator
= sfile
.active_operator
952 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
954 def draw(self
, context
):
956 layout
.use_property_split
= True
957 layout
.use_property_decorate
= False # No animation.
959 sfile
= context
.space_data
960 operator
= sfile
.active_operator
962 layout
.prop(operator
, 'export_apply')
963 layout
.prop(operator
, 'export_texcoords')
964 layout
.prop(operator
, 'export_normals')
965 col
= layout
.column()
966 col
.active
= operator
.export_normals
967 col
.prop(operator
, 'export_tangents')
968 layout
.prop(operator
, 'export_colors')
969 layout
.prop(operator
, 'export_attributes')
971 col
= layout
.column()
972 col
.prop(operator
, 'use_mesh_edges')
973 col
.prop(operator
, 'use_mesh_vertices')
976 class GLTF_PT_export_data_material(bpy
.types
.Panel
):
977 bl_space_type
= 'FILE_BROWSER'
978 bl_region_type
= 'TOOL_PROPS'
979 bl_label
= "Material"
980 bl_parent_id
= "GLTF_PT_export_data"
981 bl_options
= {'DEFAULT_CLOSED'}
984 def poll(cls
, context
):
985 sfile
= context
.space_data
986 operator
= sfile
.active_operator
987 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
989 def draw(self
, context
):
991 layout
.use_property_split
= True
992 layout
.use_property_decorate
= False # No animation.
994 sfile
= context
.space_data
995 operator
= sfile
.active_operator
997 layout
.prop(operator
, 'export_materials')
998 col
= layout
.column()
999 col
.active
= operator
.export_materials
== "EXPORT"
1000 col
.prop(operator
, 'export_image_format')
1001 if operator
.export_image_format
in ["AUTO", "JPEG"]:
1002 col
.prop(operator
, 'export_jpeg_quality')
1004 class GLTF_PT_export_data_original_pbr(bpy
.types
.Panel
):
1005 bl_space_type
= 'FILE_BROWSER'
1006 bl_region_type
= 'TOOL_PROPS'
1007 bl_label
= "PBR Extensions"
1008 bl_parent_id
= "GLTF_PT_export_data_material"
1009 bl_options
= {'DEFAULT_CLOSED'}
1012 def poll(cls
, context
):
1013 sfile
= context
.space_data
1014 operator
= sfile
.active_operator
1015 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1017 def draw(self
, context
):
1018 layout
= self
.layout
1019 layout
.use_property_split
= True
1020 layout
.use_property_decorate
= False # No animation.
1022 sfile
= context
.space_data
1023 operator
= sfile
.active_operator
1025 layout
.prop(operator
, 'export_original_specular')
1027 class GLTF_PT_export_data_lighting(bpy
.types
.Panel
):
1028 bl_space_type
= 'FILE_BROWSER'
1029 bl_region_type
= 'TOOL_PROPS'
1030 bl_label
= "Lighting"
1031 bl_parent_id
= "GLTF_PT_export_data"
1032 bl_options
= {'DEFAULT_CLOSED'}
1035 def poll(cls
, context
):
1036 sfile
= context
.space_data
1037 operator
= sfile
.active_operator
1038 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1040 def draw(self
, context
):
1041 layout
= self
.layout
1042 layout
.use_property_split
= True
1043 layout
.use_property_decorate
= False # No animation.
1045 sfile
= context
.space_data
1046 operator
= sfile
.active_operator
1048 layout
.prop(operator
, 'export_import_convert_lighting_mode')
1050 class GLTF_PT_export_data_shapekeys(bpy
.types
.Panel
):
1051 bl_space_type
= 'FILE_BROWSER'
1052 bl_region_type
= 'TOOL_PROPS'
1053 bl_label
= "Shape Keys"
1054 bl_parent_id
= "GLTF_PT_export_data"
1055 bl_options
= {'DEFAULT_CLOSED'}
1058 def poll(cls
, context
):
1059 sfile
= context
.space_data
1060 operator
= sfile
.active_operator
1062 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1064 def draw_header(self
, context
):
1065 sfile
= context
.space_data
1066 operator
= sfile
.active_operator
1067 self
.layout
.prop(operator
, "export_morph", text
="")
1069 def draw(self
, context
):
1070 layout
= self
.layout
1071 layout
.use_property_split
= True
1072 layout
.use_property_decorate
= False # No animation.
1074 sfile
= context
.space_data
1075 operator
= sfile
.active_operator
1077 layout
.active
= operator
.export_morph
1079 layout
.prop(operator
, 'export_morph_normal')
1080 col
= layout
.column()
1081 col
.active
= operator
.export_morph_normal
1082 col
.prop(operator
, 'export_morph_tangent')
1085 class GLTF_PT_export_data_skinning(bpy
.types
.Panel
):
1086 bl_space_type
= 'FILE_BROWSER'
1087 bl_region_type
= 'TOOL_PROPS'
1088 bl_label
= "Skinning"
1089 bl_parent_id
= "GLTF_PT_export_data"
1090 bl_options
= {'DEFAULT_CLOSED'}
1093 def poll(cls
, context
):
1094 sfile
= context
.space_data
1095 operator
= sfile
.active_operator
1097 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1099 def draw_header(self
, context
):
1100 sfile
= context
.space_data
1101 operator
= sfile
.active_operator
1102 self
.layout
.prop(operator
, "export_skins", text
="")
1104 def draw(self
, context
):
1105 layout
= self
.layout
1106 layout
.use_property_split
= True
1107 layout
.use_property_decorate
= False # No animation.
1109 sfile
= context
.space_data
1110 operator
= sfile
.active_operator
1112 layout
.active
= operator
.export_skins
1114 layout
.prop(operator
, 'export_all_influences')
1117 class GLTF_PT_export_data_armature(bpy
.types
.Panel
):
1118 bl_space_type
= 'FILE_BROWSER'
1119 bl_region_type
= 'TOOL_PROPS'
1120 bl_label
= "Armature"
1121 bl_parent_id
= "GLTF_PT_export_data"
1122 bl_options
= {'DEFAULT_CLOSED'}
1125 def poll(cls
, context
):
1126 sfile
= context
.space_data
1127 operator
= sfile
.active_operator
1129 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1131 def draw(self
, context
):
1132 layout
= self
.layout
1133 layout
.use_property_split
= True
1134 layout
.use_property_decorate
= False # No animation.
1136 sfile
= context
.space_data
1137 operator
= sfile
.active_operator
1139 layout
.active
= operator
.export_skins
1141 layout
.prop(operator
, 'export_rest_position_armature')
1144 row
.active
= operator
.export_force_sampling
1145 row
.prop(operator
, 'export_def_bones')
1146 if operator
.export_force_sampling
is False and operator
.export_def_bones
is True:
1147 layout
.label(text
="Export only deformation bones is not possible when not sampling animation")
1149 row
.prop(operator
, 'export_hierarchy_flatten_bones')
1151 class GLTF_PT_export_data_compression(bpy
.types
.Panel
):
1152 bl_space_type
= 'FILE_BROWSER'
1153 bl_region_type
= 'TOOL_PROPS'
1154 bl_label
= "Compression"
1155 bl_parent_id
= "GLTF_PT_export_data"
1156 bl_options
= {'DEFAULT_CLOSED'}
1159 from .io
.com
import gltf2_io_draco_compression_extension
1160 self
.is_draco_available
= gltf2_io_draco_compression_extension
.dll_exists(quiet
=True)
1163 def poll(cls
, context
):
1164 sfile
= context
.space_data
1165 operator
= sfile
.active_operator
1166 if operator
.is_draco_available
:
1167 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1169 def draw_header(self
, context
):
1170 sfile
= context
.space_data
1171 operator
= sfile
.active_operator
1172 self
.layout
.prop(operator
, "export_draco_mesh_compression_enable", text
="")
1174 def draw(self
, context
):
1175 layout
= self
.layout
1176 layout
.use_property_split
= True
1177 layout
.use_property_decorate
= False # No animation.
1179 sfile
= context
.space_data
1180 operator
= sfile
.active_operator
1182 layout
.active
= operator
.export_draco_mesh_compression_enable
1183 layout
.prop(operator
, 'export_draco_mesh_compression_level')
1185 col
= layout
.column(align
=True)
1186 col
.prop(operator
, 'export_draco_position_quantization', text
="Quantize Position")
1187 col
.prop(operator
, 'export_draco_normal_quantization', text
="Normal")
1188 col
.prop(operator
, 'export_draco_texcoord_quantization', text
="Tex Coord")
1189 col
.prop(operator
, 'export_draco_color_quantization', text
="Color")
1190 col
.prop(operator
, 'export_draco_generic_quantization', text
="Generic")
1193 class GLTF_PT_export_animation(bpy
.types
.Panel
):
1194 bl_space_type
= 'FILE_BROWSER'
1195 bl_region_type
= 'TOOL_PROPS'
1196 bl_label
= "Animation"
1197 bl_parent_id
= "FILE_PT_operator"
1198 bl_options
= {'DEFAULT_CLOSED'}
1201 def poll(cls
, context
):
1202 sfile
= context
.space_data
1203 operator
= sfile
.active_operator
1205 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1207 def draw_header(self
, context
):
1208 sfile
= context
.space_data
1209 operator
= sfile
.active_operator
1210 self
.layout
.prop(operator
, "export_animations", text
="")
1212 def draw(self
, context
):
1213 layout
= self
.layout
1214 layout
.use_property_split
= True
1215 layout
.use_property_decorate
= False # No animation.
1217 sfile
= context
.space_data
1218 operator
= sfile
.active_operator
1220 layout
.active
= operator
.export_animations
1222 layout
.prop(operator
, 'export_animation_mode')
1223 if operator
.export_animation_mode
== "ACTIVE_ACTIONS":
1224 layout
.prop(operator
, 'export_nla_strips_merged_animation_name')
1227 row
.active
= operator
.export_morph
is True
1228 row
.prop(operator
, 'export_morph_animation')
1230 row
.active
= operator
.export_force_sampling
and operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS']
1231 row
.prop(operator
, 'export_bake_animation')
1232 if operator
.export_animation_mode
== "SCENE":
1233 layout
.prop(operator
, 'export_anim_scene_split_object')
1235 class GLTF_PT_export_animation_notes(bpy
.types
.Panel
):
1236 bl_space_type
= 'FILE_BROWSER'
1237 bl_region_type
= 'TOOL_PROPS'
1239 bl_parent_id
= "GLTF_PT_export_animation"
1240 bl_options
= {'DEFAULT_CLOSED'}
1243 def poll(cls
, context
):
1244 sfile
= context
.space_data
1245 operator
= sfile
.active_operator
1247 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf" and \
1248 operator
.export_animation_mode
in ["NLA_TRACKS", "SCENE"]
1250 def draw(self
, context
):
1251 operator
= context
.space_data
.active_operator
1252 layout
= self
.layout
1253 if operator
.export_animation_mode
== "SCENE":
1254 layout
.label(text
="Scene mode uses full bake mode:")
1255 layout
.label(text
="- sampling is active")
1256 layout
.label(text
="- baking all objects is active")
1257 layout
.label(text
="- Using scene frame range")
1258 elif operator
.export_animation_mode
== "NLA_TRACKS":
1259 layout
.label(text
="Track mode uses full bake mode:")
1260 layout
.label(text
="- sampling is active")
1261 layout
.label(text
="- baking all objects is active")
1263 class GLTF_PT_export_animation_ranges(bpy
.types
.Panel
):
1264 bl_space_type
= 'FILE_BROWSER'
1265 bl_region_type
= 'TOOL_PROPS'
1266 bl_label
= "Rest & Ranges"
1267 bl_parent_id
= "GLTF_PT_export_animation"
1268 bl_options
= {'DEFAULT_CLOSED'}
1271 def poll(cls
, context
):
1272 sfile
= context
.space_data
1273 operator
= sfile
.active_operator
1275 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1277 def draw(self
, context
):
1278 layout
= self
.layout
1279 layout
.use_property_split
= True
1280 layout
.use_property_decorate
= False # No animation.
1282 sfile
= context
.space_data
1283 operator
= sfile
.active_operator
1285 layout
.active
= operator
.export_animations
1287 layout
.prop(operator
, 'export_current_frame')
1289 row
.active
= operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS', 'NLA_TRACKS']
1290 row
.prop(operator
, 'export_frame_range')
1291 layout
.prop(operator
, 'export_anim_slide_to_zero')
1293 row
.active
= operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS', 'NLA_TRACKS']
1294 layout
.prop(operator
, 'export_negative_frame')
1296 class GLTF_PT_export_animation_armature(bpy
.types
.Panel
):
1297 bl_space_type
= 'FILE_BROWSER'
1298 bl_region_type
= 'TOOL_PROPS'
1299 bl_label
= "Armature"
1300 bl_parent_id
= "GLTF_PT_export_animation"
1301 bl_options
= {'DEFAULT_CLOSED'}
1304 def poll(cls
, context
):
1305 sfile
= context
.space_data
1306 operator
= sfile
.active_operator
1308 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1310 def draw(self
, context
):
1311 layout
= self
.layout
1312 layout
.use_property_split
= True
1313 layout
.use_property_decorate
= False # No animation.
1315 sfile
= context
.space_data
1316 operator
= sfile
.active_operator
1318 layout
.active
= operator
.export_animations
1320 layout
.prop(operator
, 'export_anim_single_armature')
1321 layout
.prop(operator
, 'export_reset_pose_bones')
1323 class GLTF_PT_export_animation_sampling(bpy
.types
.Panel
):
1324 bl_space_type
= 'FILE_BROWSER'
1325 bl_region_type
= 'TOOL_PROPS'
1326 bl_label
= "Sampling Animations"
1327 bl_parent_id
= "GLTF_PT_export_animation"
1328 bl_options
= {'DEFAULT_CLOSED'}
1331 def poll(cls
, context
):
1332 sfile
= context
.space_data
1333 operator
= sfile
.active_operator
1335 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1337 def draw_header(self
, context
):
1338 sfile
= context
.space_data
1339 operator
= sfile
.active_operator
1340 self
.layout
.active
= operator
.export_animations
and operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS']
1341 self
.layout
.prop(operator
, "export_force_sampling", text
="")
1343 def draw(self
, context
):
1344 layout
= self
.layout
1345 layout
.use_property_split
= True
1346 layout
.use_property_decorate
= False # No animation.
1348 sfile
= context
.space_data
1349 operator
= sfile
.active_operator
1351 layout
.active
= operator
.export_animations
1353 layout
.prop(operator
, 'export_frame_step')
1356 class GLTF_PT_export_animation_optimize(bpy
.types
.Panel
):
1357 bl_space_type
= 'FILE_BROWSER'
1358 bl_region_type
= 'TOOL_PROPS'
1359 bl_label
= "Optimize Animations"
1360 bl_parent_id
= "GLTF_PT_export_animation"
1361 bl_options
= {'DEFAULT_CLOSED'}
1364 def poll(cls
, context
):
1365 sfile
= context
.space_data
1366 operator
= sfile
.active_operator
1368 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1370 def draw(self
, context
):
1371 layout
= self
.layout
1372 layout
.use_property_split
= True
1373 layout
.use_property_decorate
= False # No animation.
1375 sfile
= context
.space_data
1376 operator
= sfile
.active_operator
1378 layout
.active
= operator
.export_animations
1380 layout
.prop(operator
, 'export_optimize_animation_size')
1383 row
.prop(operator
, 'export_optimize_animation_keep_anim_armature')
1386 row
.prop(operator
, 'export_optimize_animation_keep_anim_object')
1389 class GLTF_PT_export_user_extensions(bpy
.types
.Panel
):
1390 bl_space_type
= 'FILE_BROWSER'
1391 bl_region_type
= 'TOOL_PROPS'
1392 bl_label
= "Exporter Extensions"
1393 bl_parent_id
= "FILE_PT_operator"
1394 bl_options
= {'DEFAULT_CLOSED'}
1397 def poll(cls
, context
):
1398 sfile
= context
.space_data
1399 operator
= sfile
.active_operator
1401 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf" and operator
.has_active_exporter_extensions
1403 def draw(self
, context
):
1404 layout
= self
.layout
1405 layout
.use_property_split
= True
1406 layout
.use_property_decorate
= False # No animation.
1408 class GLTF_PT_import_user_extensions(bpy
.types
.Panel
):
1409 bl_space_type
= 'FILE_BROWSER'
1410 bl_region_type
= 'TOOL_PROPS'
1411 bl_label
= "Importer Extensions"
1412 bl_parent_id
= "FILE_PT_operator"
1413 bl_options
= {'DEFAULT_CLOSED'}
1416 def poll(cls
, context
):
1417 sfile
= context
.space_data
1418 operator
= sfile
.active_operator
1419 return operator
.bl_idname
== "IMPORT_SCENE_OT_gltf" and operator
.has_active_importer_extensions
1421 def draw(self
, context
):
1422 layout
= self
.layout
1423 layout
.use_property_split
= True
1424 layout
.use_property_decorate
= False # No animation.
1426 class ExportGLTF2(bpy
.types
.Operator
, ExportGLTF2_Base
, ExportHelper
):
1427 """Export scene as glTF 2.0 file"""
1428 bl_idname
= 'export_scene.gltf'
1429 bl_label
= 'Export glTF 2.0'
1433 filter_glob
: StringProperty(default
='*.glb', options
={'HIDDEN'})
1436 def menu_func_export(self
, context
):
1437 self
.layout
.operator(ExportGLTF2
.bl_idname
, text
='glTF 2.0 (.glb/.gltf)')
1440 class ImportGLTF2(Operator
, ConvertGLTF2_Base
, ImportHelper
):
1441 """Load a glTF 2.0 file"""
1442 bl_idname
= 'import_scene.gltf'
1443 bl_label
= 'Import glTF 2.0'
1444 bl_options
= {'REGISTER', 'UNDO'}
1446 filter_glob
: StringProperty(default
="*.glb;*.gltf", options
={'HIDDEN'})
1448 files
: CollectionProperty(
1450 type=bpy
.types
.OperatorFileListElement
,
1453 loglevel
: IntProperty(
1455 description
="Log Level")
1457 import_pack_images
: BoolProperty(
1459 description
='Pack all images into .blend file',
1463 merge_vertices
: BoolProperty(
1464 name
='Merge Vertices',
1466 'The glTF format requires discontinuous normals, UVs, and '
1467 'other vertex attributes to be stored as separate vertices, '
1468 'as required for rendering on typical graphics hardware. '
1469 'This option attempts to combine co-located vertices where possible. '
1470 'Currently cannot combine verts with different normals'
1475 import_shading
: EnumProperty(
1477 items
=(("NORMALS", "Use Normal Data", ""),
1478 ("FLAT", "Flat Shading", ""),
1479 ("SMOOTH", "Smooth Shading", "")),
1480 description
="How normals are computed during import",
1483 bone_heuristic
: EnumProperty(
1486 ("BLENDER", "Blender (best for re-importing)",
1487 "Good for re-importing glTFs exported from Blender. "
1488 "Bone tips are placed on their local +Y axis (in glTF space)"),
1489 ("TEMPERANCE", "Temperance (average)",
1490 "Decent all-around strategy. "
1491 "A bone with one child has its tip placed on the local axis "
1492 "closest to its child"),
1493 ("FORTUNE", "Fortune (may look better, less accurate)",
1494 "Might look better than Temperance, but also might have errors. "
1495 "A bone with one child has its tip placed at its child's root. "
1496 "Non-uniform scalings may get messed up though, so beware"),
1498 description
="Heuristic for placing bones. Tries to make bones pretty",
1499 default
="TEMPERANCE",
1502 guess_original_bind_pose
: BoolProperty(
1503 name
='Guess Original Bind Pose',
1505 'Try to guess the original bind pose for skinned meshes from '
1506 'the inverse bind matrices. '
1507 'When off, use default/rest pose as bind pose'
1512 def draw(self
, context
):
1513 layout
= self
.layout
1515 layout
.use_property_split
= True
1516 layout
.use_property_decorate
= False # No animation.
1518 layout
.prop(self
, 'import_pack_images')
1519 layout
.prop(self
, 'merge_vertices')
1520 layout
.prop(self
, 'import_shading')
1521 layout
.prop(self
, 'guess_original_bind_pose')
1522 layout
.prop(self
, 'bone_heuristic')
1523 layout
.prop(self
, 'export_import_convert_lighting_mode')
1525 def invoke(self
, context
, event
):
1527 preferences
= bpy
.context
.preferences
1528 for addon_name
in preferences
.addons
.keys():
1530 if hasattr(sys
.modules
[addon_name
], 'glTF2ImportUserExtension') or hasattr(sys
.modules
[addon_name
], 'glTF2ImportUserExtensions'):
1531 importer_extension_panel_unregister_functors
.append(sys
.modules
[addon_name
].register_panel())
1535 self
.has_active_importer_extensions
= len(importer_extension_panel_unregister_functors
) > 0
1536 return ImportHelper
.invoke(self
, context
, event
)
1538 def execute(self
, context
):
1539 return self
.import_gltf2(context
)
1541 def import_gltf2(self
, context
):
1544 self
.set_debug_log()
1545 import_settings
= self
.as_keywords()
1547 user_extensions
= []
1550 preferences
= bpy
.context
.preferences
1551 for addon_name
in preferences
.addons
.keys():
1553 module
= sys
.modules
[addon_name
]
1556 if hasattr(module
, 'glTF2ImportUserExtension'):
1557 extension_ctor
= module
.glTF2ImportUserExtension
1558 user_extensions
.append(extension_ctor())
1559 import_settings
['import_user_extensions'] = user_extensions
1562 # Multiple file import
1564 dirname
= os
.path
.dirname(self
.filepath
)
1565 for file in self
.files
:
1566 path
= os
.path
.join(dirname
, file.name
)
1567 if self
.unit_import(path
, import_settings
) == {'FINISHED'}:
1571 # Single file import
1572 return self
.unit_import(self
.filepath
, import_settings
)
1574 def unit_import(self
, filename
, import_settings
):
1576 from .io
.imp
.gltf2_io_gltf
import glTFImporter
, ImportError
1577 from .blender
.imp
.gltf2_blender_gltf
import BlenderGlTF
1580 gltf_importer
= glTFImporter(filename
, import_settings
)
1581 gltf_importer
.read()
1582 gltf_importer
.checks()
1584 print("Data are loaded, start creating Blender stuff")
1586 start_time
= time
.time()
1587 BlenderGlTF
.create(gltf_importer
)
1588 elapsed_s
= "{:.2f}s".format(time
.time() - start_time
)
1589 print("glTF import finished in " + elapsed_s
)
1591 gltf_importer
.log
.removeHandler(gltf_importer
.log_handler
)
1595 except ImportError as e
:
1596 self
.report({'ERROR'}, e
.args
[0])
1597 return {'CANCELLED'}
1599 def set_debug_log(self
):
1601 if bpy
.app
.debug_value
== 0:
1602 self
.loglevel
= logging
.CRITICAL
1603 elif bpy
.app
.debug_value
== 1:
1604 self
.loglevel
= logging
.ERROR
1605 elif bpy
.app
.debug_value
== 2:
1606 self
.loglevel
= logging
.WARNING
1607 elif bpy
.app
.debug_value
== 3:
1608 self
.loglevel
= logging
.INFO
1610 self
.loglevel
= logging
.NOTSET
1613 def gltf_variant_ui_update(self
, context
):
1614 from .blender
.com
.gltf2_blender_ui
import variant_register
, variant_unregister
1615 if self
.KHR_materials_variants_ui
is True:
1616 # register all needed types
1619 variant_unregister()
1621 def gltf_animation_ui_update(self
, context
):
1622 from .blender
.com
.gltf2_blender_ui
import anim_ui_register
, anim_ui_unregister
1623 if self
.animation_ui
is True:
1624 # register all needed types
1627 anim_ui_unregister()
1629 class GLTF_AddonPreferences(bpy
.types
.AddonPreferences
):
1630 bl_idname
= __package__
1632 settings_node_ui
: bpy
.props
.BoolProperty(
1634 description
="Displays glTF Material Output node in Shader Editor (Menu Add > Output)"
1637 KHR_materials_variants_ui
: bpy
.props
.BoolProperty(
1639 description
="Displays glTF UI to manage material variants",
1640 update
=gltf_variant_ui_update
1643 animation_ui
: bpy
.props
.BoolProperty(
1645 description
="Display glTF UI to manage animations",
1646 update
=gltf_animation_ui_update
1649 def draw(self
, context
):
1650 layout
= self
.layout
1652 row
.prop(self
, "settings_node_ui", text
="Shader Editor Add-ons")
1653 row
.prop(self
, "KHR_materials_variants_ui", text
="Material Variants")
1654 row
.prop(self
, "animation_ui", text
="Animation UI")
1656 def menu_func_import(self
, context
):
1657 self
.layout
.operator(ImportGLTF2
.bl_idname
, text
='glTF 2.0 (.glb/.gltf)')
1662 GLTF_PT_export_main
,
1663 GLTF_PT_export_include
,
1664 GLTF_PT_export_transform
,
1665 GLTF_PT_export_data
,
1666 GLTF_PT_export_data_mesh
,
1667 GLTF_PT_export_data_material
,
1668 GLTF_PT_export_data_original_pbr
,
1669 GLTF_PT_export_data_shapekeys
,
1670 GLTF_PT_export_data_armature
,
1671 GLTF_PT_export_data_skinning
,
1672 GLTF_PT_export_data_lighting
,
1673 GLTF_PT_export_data_compression
,
1674 GLTF_PT_export_animation
,
1675 GLTF_PT_export_animation_notes
,
1676 GLTF_PT_export_animation_ranges
,
1677 GLTF_PT_export_animation_armature
,
1678 GLTF_PT_export_animation_sampling
,
1679 GLTF_PT_export_animation_optimize
,
1680 GLTF_PT_export_user_extensions
,
1682 GLTF_PT_import_user_extensions
,
1683 GLTF_AddonPreferences
1688 from .blender
.com
import gltf2_blender_ui
as blender_ui
1690 bpy
.utils
.register_class(c
)
1691 # bpy.utils.register_module(__name__)
1693 blender_ui
.register()
1694 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.KHR_materials_variants_ui
is True:
1695 blender_ui
.variant_register()
1696 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.animation_ui
is True:
1697 blender_ui
.anim_ui_register()
1699 # add to the export / import menu
1700 bpy
.types
.TOPBAR_MT_file_export
.append(menu_func_export
)
1701 bpy
.types
.TOPBAR_MT_file_import
.append(menu_func_import
)
1705 from .blender
.com
import gltf2_blender_ui
as blender_ui
1706 blender_ui
.unregister()
1707 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.KHR_materials_variants_ui
is True:
1708 blender_ui
.variant_unregister()
1711 bpy
.utils
.unregister_class(c
)
1712 for f
in exporter_extension_panel_unregister_functors
:
1714 exporter_extension_panel_unregister_functors
.clear()
1716 for f
in importer_extension_panel_unregister_functors
:
1718 importer_extension_panel_unregister_functors
.clear()
1720 # bpy.utils.unregister_module(__name__)
1722 # remove from the export / import menu
1723 bpy
.types
.TOPBAR_MT_file_export
.remove(menu_func_export
)
1724 bpy
.types
.TOPBAR_MT_file_import
.remove(menu_func_import
)