1 # SPDX-FileCopyrightText: 2018-2021 The glTF-Blender-IO authors
3 # SPDX-License-Identifier: Apache-2.0
6 'name': 'glTF 2.0 format',
7 'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
10 'location': 'File > Import-Export',
11 'description': 'Import-Export as glTF 2.0',
13 'doc_url': "{BLENDER_MANUAL_URL}/addons/import_export/scene_gltf2.html",
14 'tracker_url': "https://github.com/KhronosGroup/glTF-Blender-IO/issues/",
15 'support': 'OFFICIAL',
16 'category': 'Import-Export',
19 def get_version_string():
20 return str(bl_info
['version'][0]) + '.' + str(bl_info
['version'][1]) + '.' + str(bl_info
['version'][2])
23 # Script reloading (if the user calls 'Reload Scripts' from Blender)
26 def reload_package(module_dict_main
):
28 from pathlib
import Path
30 def reload_package_recursive(current_dir
, module_dict
):
31 for path
in current_dir
.iterdir():
32 if "__init__" in str(path
) or path
.stem
not in module_dict
:
35 if path
.is_file() and path
.suffix
== ".py":
36 importlib
.reload(module_dict
[path
.stem
])
38 reload_package_recursive(path
, module_dict
[path
.stem
].__dict
__)
40 reload_package_recursive(Path(__file__
).parent
, module_dict_main
)
44 reload_package(locals())
47 from bpy
.props
import (StringProperty
,
53 from bpy
.types
import Operator
54 from bpy_extras
.io_utils
import ImportHelper
, ExportHelper
58 # Functions / Classes.
61 exporter_extension_panel_unregister_functors
= []
62 importer_extension_panel_unregister_functors
= []
65 def ensure_filepath_matches_export_format(filepath
, export_format
):
67 filename
= os
.path
.basename(filepath
)
71 stem
, ext
= os
.path
.splitext(filename
)
72 if stem
.startswith('.') and not ext
:
75 desired_ext
= '.glb' if export_format
== 'GLB' else '.gltf'
76 ext_lower
= ext
.lower()
77 if ext_lower
not in ['.glb', '.gltf']:
78 return filepath
+ desired_ext
79 elif ext_lower
!= desired_ext
:
80 filepath
= filepath
[:-len(ext
)] # strip off ext
81 return filepath
+ desired_ext
86 def on_export_format_changed(self
, context
):
87 # Update the filename in the file browser when the format (.glb/.gltf)
89 sfile
= context
.space_data
90 if not isinstance(sfile
, bpy
.types
.SpaceFileBrowser
):
92 if not sfile
.active_operator
:
94 if sfile
.active_operator
.bl_idname
!= "EXPORT_SCENE_OT_gltf":
97 sfile
.params
.filename
= ensure_filepath_matches_export_format(
98 sfile
.params
.filename
,
102 # Also change the filter
103 sfile
.params
.filter_glob
= '*.glb' if self
.export_format
== 'GLB' else '*.gltf'
104 # Force update of file list, because update the filter does not update the real file list
105 bpy
.ops
.file.refresh()
107 def on_export_action_filter_changed(self
, context
):
108 if self
.export_action_filter
is True:
109 bpy
.types
.Scene
.gltf_action_filter
= bpy
.props
.CollectionProperty(type=GLTF2_filter_action
)
110 bpy
.types
.Scene
.gltf_action_filter_active
= bpy
.props
.IntProperty()
112 for action
in bpy
.data
.actions
:
113 if id(action
) not in [id(item
.action
) for item
in bpy
.data
.scenes
[0].gltf_action_filter
]:
114 item
= bpy
.data
.scenes
[0].gltf_action_filter
.add()
119 bpy
.data
.scenes
[0].gltf_action_filter
.clear()
120 del bpy
.types
.Scene
.gltf_action_filter
121 del bpy
.types
.Scene
.gltf_action_filter_active
126 class ConvertGLTF2_Base
:
127 """Base class containing options that should be exposed during both import and export."""
129 export_import_convert_lighting_mode
: EnumProperty(
130 name
='Lighting Mode',
132 ('SPEC', 'Standard', 'Physically-based glTF lighting units (cd, lx, nt)'),
133 ('COMPAT', 'Unitless', 'Non-physical, unitless lighting. Useful when exposure controls are not available'),
134 ('RAW', 'Raw (Deprecated)', 'Blender lighting strengths with no conversion'),
136 description
='Optional backwards compatibility for non-standard render engines. Applies to lights',# TODO: and emissive materials',
140 class ExportGLTF2_Base(ConvertGLTF2_Base
):
141 # TODO: refactor to avoid boilerplate
144 from .io
.com
import gltf2_io_draco_compression_extension
145 self
.is_draco_available
= gltf2_io_draco_compression_extension
.dll_exists()
147 bl_options
= {'PRESET'}
149 # Don't use export_ prefix here, I don't want it to be saved with other export settings
150 gltf_export_id
: StringProperty(
153 'Identifier of caller (in case of add-on calling this exporter). '
154 'Can be useful in case of Extension added by other add-ons'
159 # gltfpack properties
160 export_use_gltfpack
: BoolProperty(
162 description
='Use gltfpack to simplify the mesh and/or compress its textures',
166 export_gltfpack_tc
: BoolProperty(
167 name
='KTX2 Compression',
168 description
='Convert all textures to KTX2 with BasisU supercompression',
172 export_gltfpack_tq
: IntProperty(
173 name
='Texture Encoding Quality',
174 description
='Texture encoding quality',
180 export_gltfpack_si
: FloatProperty(
181 name
='Mesh Simplification Ratio',
182 description
='Simplify meshes targeting triangle count ratio',
188 export_gltfpack_sa
: BoolProperty(
189 name
='Aggressive Mesh Simplification',
190 description
='Aggressively simplify to the target ratio disregarding quality',
194 export_gltfpack_slb
: BoolProperty(
195 name
='Lock Mesh Border Vertices',
196 description
='Lock border vertices during simplification to avoid gaps on connected meshes',
200 export_gltfpack_vp
: IntProperty(
201 name
='Position Quantization',
202 description
='Use N-bit quantization for positions',
208 export_gltfpack_vt
: IntProperty(
209 name
='Texture Coordinate Quantization',
210 description
='Use N-bit quantization for texture coordinates',
216 export_gltfpack_vn
: IntProperty(
217 name
='Normal/Tangent Quantization',
218 description
='Use N-bit quantization for normals and tangents',
224 export_gltfpack_vc
: IntProperty(
225 name
='Vertex Color Quantization',
226 description
='Use N-bit quantization for colors',
232 export_gltfpack_vpi
: EnumProperty(
233 name
='Vertex Position Attributes',
234 description
='Type to use for vertex position attributes',
235 items
=(('Integer', 'Integer', 'Use integer attributes for positions'),
236 ('Normalized', 'Normalized', 'Use normalized attributes for positions'),
237 ('Floating-point', 'Floating-point', 'Use floating-point attributes for positions')),
241 export_gltfpack_noq
: BoolProperty(
242 name
='Disable Quantization',
243 description
='Disable quantization; produces much larger glTF files with no extensions',
247 # TODO: some stuff in Textures
253 # TODO: some stuff in Miscellaneous
255 export_format
: EnumProperty(
257 items
=(('GLB', 'glTF Binary (.glb)',
258 'Exports a single file, with all data packed in binary form. '
259 'Most efficient and portable, but more difficult to edit later'),
260 ('GLTF_SEPARATE', 'glTF Separate (.gltf + .bin + textures)',
261 'Exports multiple files, with separate JSON, binary and texture data. '
262 'Easiest to edit later')),
264 'Output format. Binary is most efficient, '
265 'but JSON may be easier to edit later'
267 default
='GLB', #Warning => If you change the default, need to change the default filter too
268 update
=on_export_format_changed
,
271 ui_tab
: EnumProperty(
272 items
=(('GENERAL', "General", "General settings"),
273 ('MESHES', "Meshes", "Mesh settings"),
274 ('OBJECTS', "Objects", "Object settings"),
275 ('ANIMATION', "Animation", "Animation settings")),
277 description
="Export setting categories",
280 export_copyright
: StringProperty(
282 description
='Legal rights and conditions for the model',
286 export_image_format
: EnumProperty(
288 items
=(('AUTO', 'Automatic',
289 'Save PNGs as PNGs, JPEGs as JPEGs, WebPs as WebPs. '
290 'For other formats, use PNG'),
291 ('JPEG', 'JPEG Format (.jpg)',
292 'Save images as JPEGs. (Images that need alpha are saved as PNGs though.) '
293 'Be aware of a possible loss in quality'),
294 ('WEBP', 'WebP Format',
295 'Save images as WebPs as main image (no fallback)'),
297 'Don\'t export images'),
300 'Output format for images. PNG is lossless and generally preferred, but JPEG might be preferable for web '
301 'applications due to the smaller file size. Alternatively they can be omitted if they are not needed'
306 export_image_add_webp
: BoolProperty(
309 "Creates WebP textures for every texture. "
310 "For already WebP textures, nothing happens"
315 export_image_webp_fallback
: BoolProperty(
316 name
='WebP fallback',
318 "For all WebP textures, create a PNG fallback texture"
323 export_texture_dir
: StringProperty(
325 description
='Folder to place texture files in. Relative to the .gltf file',
329 # Keep for back compatibility
330 export_jpeg_quality
: IntProperty(
332 description
='Quality of JPEG export',
338 # Keep for back compatibility
339 export_image_quality
: IntProperty(
340 name
='Image quality',
341 description
='Quality of image export',
347 export_keep_originals
: BoolProperty(
348 name
='Keep original',
349 description
=('Keep original textures files if possible. '
350 'WARNING: if you use more than one texture, '
351 'where pbr standard requires only one, only one texture will be used. '
352 'This can lead to unexpected results'
357 export_texcoords
: BoolProperty(
359 description
='Export UVs (texture coordinates) with meshes',
363 export_normals
: BoolProperty(
365 description
='Export vertex normals with meshes',
369 export_gn_mesh
: BoolProperty(
370 name
='Geometry Nodes Instances (Experimental)',
371 description
='Export Geometry nodes instance meshes',
375 export_draco_mesh_compression_enable
: BoolProperty(
376 name
='Draco mesh compression',
377 description
='Compress mesh using Draco',
381 export_draco_mesh_compression_level
: IntProperty(
382 name
='Compression level',
383 description
='Compression level (0 = most speed, 6 = most compression, higher values currently not supported)',
389 export_draco_position_quantization
: IntProperty(
390 name
='Position quantization bits',
391 description
='Quantization bits for position values (0 = no quantization)',
397 export_draco_normal_quantization
: IntProperty(
398 name
='Normal quantization bits',
399 description
='Quantization bits for normal values (0 = no quantization)',
405 export_draco_texcoord_quantization
: IntProperty(
406 name
='Texcoord quantization bits',
407 description
='Quantization bits for texture coordinate values (0 = no quantization)',
413 export_draco_color_quantization
: IntProperty(
414 name
='Color quantization bits',
415 description
='Quantization bits for color values (0 = no quantization)',
421 export_draco_generic_quantization
: IntProperty(
422 name
='Generic quantization bits',
423 description
='Quantization bits for generic values like weights or joints (0 = no quantization)',
429 export_tangents
: BoolProperty(
431 description
='Export vertex tangents with meshes',
435 export_materials
: EnumProperty(
437 items
=(('EXPORT', 'Export',
438 'Export all materials used by included objects'),
439 ('PLACEHOLDER', 'Placeholder',
440 'Do not export materials, but write multiple primitive groups per mesh, keeping material slot information'),
441 ('NONE', 'No export',
442 'Do not export materials, and combine mesh primitive groups, losing material slot information')),
443 description
='Export materials',
447 export_unused_images
: BoolProperty(
448 name
='Unused images',
449 description
='Export images not assigned to any material',
452 export_unused_textures
: BoolProperty(
453 name
='Prepare Unused textures',
455 'Export image texture nodes not assigned to any material. '
456 'This feature is not standard and needs an external extension to be included in the glTF file'
460 export_colors
: BoolProperty(
462 description
='Keep for compatibility only',
466 export_attributes
: BoolProperty(
468 description
='Export Attributes (when starting with underscore)',
472 use_mesh_edges
: BoolProperty(
475 'Export loose edges as lines, using the material from the first material slot'
480 use_mesh_vertices
: BoolProperty(
483 'Export loose points as glTF points, using the material from the first material slot'
488 export_cameras
: BoolProperty(
490 description
='Export cameras',
494 use_selection
: BoolProperty(
495 name
='Selected Objects',
496 description
='Export selected objects only',
500 use_visible
: BoolProperty(
501 name
='Visible Objects',
502 description
='Export visible objects only',
506 use_renderable
: BoolProperty(
507 name
='Renderable Objects',
508 description
='Export renderable objects only',
512 use_active_collection_with_nested
: BoolProperty(
513 name
='Include Nested Collections',
514 description
='Include active collection and nested collections',
518 use_active_collection
: BoolProperty(
519 name
='Active Collection',
520 description
='Export objects in the active collection only',
524 use_active_scene
: BoolProperty(
526 description
='Export active scene only',
530 export_extras
: BoolProperty(
531 name
='Custom Properties',
532 description
='Export custom properties as glTF extras',
536 export_yup
: BoolProperty(
538 description
='Export using glTF convention, +Y up',
542 export_apply
: BoolProperty(
543 name
='Apply Modifiers',
544 description
='Apply modifiers (excluding Armatures) to mesh objects -'
545 'WARNING: prevents exporting shape keys',
549 export_shared_accessors
: BoolProperty(
550 name
='Shared Accessors',
551 description
='Export Primitives using shared accessors for attributes',
555 export_animations
: BoolProperty(
557 description
='Exports active actions and NLA tracks as glTF animations',
561 export_frame_range
: BoolProperty(
562 name
='Limit to Playback Range',
563 description
='Clips animations to selected playback range',
567 export_frame_step
: IntProperty(
568 name
='Sampling Rate',
569 description
='How often to evaluate animated values (in frames)',
575 export_force_sampling
: BoolProperty(
576 name
='Always Sample Animations',
577 description
='Apply sampling to all animations',
581 export_animation_mode
: EnumProperty(
582 name
='Animation mode',
583 items
=(('ACTIONS', 'Actions',
584 'Export actions (actives and on NLA tracks) as separate animations'),
585 ('ACTIVE_ACTIONS', 'Active actions merged',
586 'All the currently assigned actions become one glTF animation'),
587 ('NLA_TRACKS', 'NLA Tracks',
588 'Export individual NLA Tracks as separate animation'),
590 'Export baked scene as a single animation')
592 description
='Export Animation mode',
596 export_nla_strips_merged_animation_name
: StringProperty(
597 name
='Merged Animation Name',
599 "Name of single glTF animation to be exported"
604 export_def_bones
: BoolProperty(
605 name
='Export Deformation Bones Only',
606 description
='Export Deformation bones only',
610 export_hierarchy_flatten_bones
: BoolProperty(
611 name
='Flatten Bone Hierarchy',
612 description
='Flatten Bone Hierarchy. Useful in case of non decomposable transformation matrix',
616 export_hierarchy_flatten_objs
: BoolProperty(
617 name
='Flatten Object Hierarchy',
618 description
='Flatten Object Hierarchy. Useful in case of non decomposable transformation matrix',
622 export_armature_object_remove
: BoolProperty(
623 name
='Remove Armature Object',
625 'Remove Armature object if possible. '
626 'If Armature has multiple root bones, object will not be removed'
631 export_optimize_animation_size
: BoolProperty(
632 name
='Optimize Animation Size',
634 "Reduce exported file size by removing duplicate keyframes"
639 export_optimize_animation_keep_anim_armature
: BoolProperty(
640 name
='Force keeping channels for bones',
642 "If all keyframes are identical in a rig, "
643 "force keeping the minimal animation. "
644 "When off, all possible channels for "
645 "the bones will be exported, even if empty "
646 "(minimal animation, 2 keyframes)"
651 export_optimize_animation_keep_anim_object
: BoolProperty(
652 name
='Force keeping channel for objects',
654 "If all keyframes are identical for object transformations, "
655 "force keeping the minimal animation"
660 export_negative_frame
: EnumProperty(
661 name
='Negative Frames',
662 items
=(('SLIDE', 'Slide',
663 'Slide animation to start at frame 0'),
665 'Keep only frames above frame 0'),
667 description
='Negative Frames are slid or cropped',
671 export_anim_slide_to_zero
: BoolProperty(
672 name
='Set all glTF Animation starting at 0',
674 "Set all glTF animation starting at 0.0s. "
675 "Can be useful for looping animations"
680 export_bake_animation
: BoolProperty(
681 name
='Bake All Objects Animations',
683 "Force exporting animation on every object. "
684 "Can be useful when using constraints or driver. "
685 "Also useful when exporting only selection"
690 export_anim_single_armature
: BoolProperty(
691 name
='Export all Armature Actions',
693 "Export all actions, bound to a single armature. "
694 "WARNING: Option does not support exports including multiple armatures"
699 export_reset_pose_bones
: BoolProperty(
700 name
='Reset pose bones between actions',
702 "Reset pose bones between each action exported. "
703 "This is needed when some bones are not keyed on some animations"
708 export_current_frame
: BoolProperty(
709 name
='Use Current Frame as Object Rest Transformations',
711 'Export the scene in the current animation frame. '
712 'When off, frame 0 is used as rest transformations for objects'
717 export_rest_position_armature
: BoolProperty(
718 name
='Use Rest Position Armature',
720 "Export armatures using rest position as joints' rest pose. "
721 "When off, current frame pose is used as rest pose"
726 export_anim_scene_split_object
: BoolProperty(
727 name
='Split Animation by Object',
729 "Export Scene as seen in Viewport, "
730 "But split animation by Object"
735 export_skins
: BoolProperty(
737 description
='Export skinning (armature) data',
741 export_influence_nb
: IntProperty(
742 name
='Bone Influences',
743 description
='Choose how many Bone influences to export',
748 export_all_influences
: BoolProperty(
749 name
='Include All Bone Influences',
750 description
='Allow export of all joint vertex influences. Models may appear incorrectly in many viewers',
754 export_morph
: BoolProperty(
756 description
='Export shape keys (morph targets)',
760 export_morph_normal
: BoolProperty(
761 name
='Shape Key Normals',
762 description
='Export vertex normals with shape keys (morph targets)',
766 export_morph_tangent
: BoolProperty(
767 name
='Shape Key Tangents',
768 description
='Export vertex tangents with shape keys (morph targets)',
772 export_morph_animation
: BoolProperty(
773 name
='Shape Key Animations',
774 description
='Export shape keys animations (morph targets)',
778 export_morph_reset_sk_data
: BoolProperty(
779 name
='Reset shape keys between actions',
781 "Reset shape keys between each action exported. "
782 "This is needed when some SK channels are not keyed on some animations"
787 export_lights
: BoolProperty(
788 name
='Punctual Lights',
789 description
='Export directional, point, and spot lights. '
790 'Uses "KHR_lights_punctual" glTF extension',
794 export_try_sparse_sk
: BoolProperty(
795 name
='Use Sparse Accessor if better',
796 description
='Try using Sparse Accessor if it saves space',
800 export_try_omit_sparse_sk
: BoolProperty(
801 name
='Omitting Sparse Accessor if data is empty',
802 description
='Omitting Sparse Accessor if data is empty',
806 export_gpu_instances
: BoolProperty(
807 name
='GPU Instances',
808 description
='Export using EXT_mesh_gpu_instancing. '
809 'Limited to children of a given Empty. '
810 'Multiple materials might be omitted',
814 export_action_filter
: BoolProperty(
815 name
='Filter Actions',
816 description
='Filter Actions to be exported',
818 update
=on_export_action_filter_changed
,
821 # This parameter is only here for backward compatibility, as this option is removed in 3.6
822 # This option does nothing, and is not displayed in UI
823 # What you are looking for is probably "export_animation_mode"
824 export_nla_strips
: BoolProperty(
825 name
='Group by NLA Track',
827 "When on, multiple actions become part of the same glTF animation if "
828 "they're pushed onto NLA tracks with the same name. "
829 "When off, all the currently assigned actions become one glTF animation"
834 # Keep for back compatibility, but no more used
835 export_original_specular
: BoolProperty(
836 name
='Export original PBR Specular',
838 'Export original glTF PBR Specular, instead of Blender Principled Shader Specular'
843 will_save_settings
: BoolProperty(
844 name
='Remember Export Settings',
845 description
='Store glTF export settings in the Blender project',
848 export_hierarchy_full_collections
: BoolProperty(
849 name
='Full Collection Hierarchy',
850 description
='Export full hierarchy, including intermediate collections',
854 # Custom scene property for saving settings
855 scene_key
= "glTF2ExportSettings"
859 def check(self
, _context
):
860 # Ensure file extension matches format
861 old_filepath
= self
.filepath
862 self
.filepath
= ensure_filepath_matches_export_format(
866 return self
.filepath
!= old_filepath
868 def invoke(self
, context
, event
):
869 settings
= context
.scene
.get(self
.scene_key
)
870 self
.will_save_settings
= False
873 for (k
, v
) in settings
.items():
875 self
.will_save_settings
= True
877 # Update filter if user saved settings
878 if hasattr(self
, 'export_format'):
879 self
.filter_glob
= '*.glb' if self
.export_format
== 'GLB' else '*.gltf'
881 except (AttributeError, TypeError):
882 self
.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
883 del context
.scene
[self
.scene_key
]
886 preferences
= bpy
.context
.preferences
887 for addon_name
in preferences
.addons
.keys():
889 if hasattr(sys
.modules
[addon_name
], 'glTF2ExportUserExtension') or hasattr(sys
.modules
[addon_name
], 'glTF2ExportUserExtensions'):
890 exporter_extension_panel_unregister_functors
.append(sys
.modules
[addon_name
].register_panel())
894 self
.has_active_exporter_extensions
= len(exporter_extension_panel_unregister_functors
) > 0
895 return ExportHelper
.invoke(self
, context
, event
)
897 def save_settings(self
, context
):
898 # find all props to save
900 # options that don't start with 'export_'
904 'use_active_collection_with_nested',
905 'use_active_collection',
910 all_props
= self
.properties
912 x
: getattr(self
, x
) for x
in dir(all_props
)
913 if (x
.startswith("export_") or x
in exceptional
) and all_props
.get(x
) is not None
915 context
.scene
[self
.scene_key
] = export_props
917 def execute(self
, context
):
920 from .blender
.exp
import gltf2_blender_export
921 from .io
.com
.gltf2_io_path
import path_to_uri
923 if self
.will_save_settings
:
924 self
.save_settings(context
)
926 self
.check(context
) # ensure filepath has the right extension
928 # All custom export settings are stored in this container.
931 export_settings
['exported_images'] = {}
932 export_settings
['exported_texture_nodes'] = []
933 export_settings
['additional_texture_export'] = []
934 export_settings
['additional_texture_export_current_idx'] = 0
936 export_settings
['timestamp'] = datetime
.datetime
.now()
937 export_settings
['gltf_export_id'] = self
.gltf_export_id
938 export_settings
['gltf_filepath'] = self
.filepath
939 export_settings
['gltf_filedirectory'] = os
.path
.dirname(export_settings
['gltf_filepath']) + '/'
940 export_settings
['gltf_texturedirectory'] = os
.path
.join(
941 export_settings
['gltf_filedirectory'],
942 self
.export_texture_dir
,
944 export_settings
['gltf_keep_original_textures'] = self
.export_keep_originals
946 export_settings
['gltf_format'] = self
.export_format
947 export_settings
['gltf_image_format'] = self
.export_image_format
948 export_settings
['gltf_add_webp'] = self
.export_image_add_webp
949 export_settings
['gltf_webp_fallback'] = self
.export_image_webp_fallback
950 export_settings
['gltf_image_quality'] = self
.export_image_quality
951 export_settings
['gltf_copyright'] = self
.export_copyright
952 export_settings
['gltf_texcoords'] = self
.export_texcoords
953 export_settings
['gltf_normals'] = self
.export_normals
954 export_settings
['gltf_tangents'] = self
.export_tangents
and self
.export_normals
955 export_settings
['gltf_loose_edges'] = self
.use_mesh_edges
956 export_settings
['gltf_loose_points'] = self
.use_mesh_vertices
958 if self
.is_draco_available
:
959 export_settings
['gltf_draco_mesh_compression'] = self
.export_draco_mesh_compression_enable
960 export_settings
['gltf_draco_mesh_compression_level'] = self
.export_draco_mesh_compression_level
961 export_settings
['gltf_draco_position_quantization'] = self
.export_draco_position_quantization
962 export_settings
['gltf_draco_normal_quantization'] = self
.export_draco_normal_quantization
963 export_settings
['gltf_draco_texcoord_quantization'] = self
.export_draco_texcoord_quantization
964 export_settings
['gltf_draco_color_quantization'] = self
.export_draco_color_quantization
965 export_settings
['gltf_draco_generic_quantization'] = self
.export_draco_generic_quantization
967 export_settings
['gltf_draco_mesh_compression'] = False
969 export_settings
['gltf_gn_mesh'] = self
.export_gn_mesh
971 export_settings
['gltf_materials'] = self
.export_materials
972 export_settings
['gltf_attributes'] = self
.export_attributes
973 export_settings
['gltf_cameras'] = self
.export_cameras
975 export_settings
['gltf_unused_textures'] = self
.export_unused_textures
976 export_settings
['gltf_unused_images'] = self
.export_unused_images
978 export_settings
['gltf_visible'] = self
.use_visible
979 export_settings
['gltf_renderable'] = self
.use_renderable
981 export_settings
['gltf_active_collection'] = self
.use_active_collection
982 if self
.use_active_collection
:
983 export_settings
['gltf_active_collection_with_nested'] = self
.use_active_collection_with_nested
985 export_settings
['gltf_active_collection_with_nested'] = False
986 export_settings
['gltf_active_scene'] = self
.use_active_scene
988 export_settings
['gltf_selected'] = self
.use_selection
989 export_settings
['gltf_layers'] = True # self.export_layers
990 export_settings
['gltf_extras'] = self
.export_extras
991 export_settings
['gltf_yup'] = self
.export_yup
992 export_settings
['gltf_apply'] = self
.export_apply
993 export_settings
['gltf_shared_accessors'] = self
.export_shared_accessors
994 export_settings
['gltf_current_frame'] = self
.export_current_frame
995 export_settings
['gltf_animations'] = self
.export_animations
996 export_settings
['gltf_def_bones'] = self
.export_def_bones
997 export_settings
['gltf_flatten_bones_hierarchy'] = self
.export_hierarchy_flatten_bones
998 export_settings
['gltf_flatten_obj_hierarchy'] = self
.export_hierarchy_flatten_objs
999 export_settings
['gltf_armature_object_remove'] = self
.export_armature_object_remove
1000 if self
.export_animations
:
1001 export_settings
['gltf_frame_range'] = self
.export_frame_range
1002 export_settings
['gltf_force_sampling'] = self
.export_force_sampling
1003 if not self
.export_force_sampling
:
1004 export_settings
['gltf_def_bones'] = False
1005 export_settings
['gltf_bake_animation'] = False
1006 export_settings
['gltf_animation_mode'] = self
.export_animation_mode
1007 if export_settings
['gltf_animation_mode'] == "NLA_TRACKS":
1008 export_settings
['gltf_force_sampling'] = True
1009 if export_settings
['gltf_animation_mode'] == "SCENE":
1010 export_settings
['gltf_anim_scene_split_object'] = self
.export_anim_scene_split_object
1012 export_settings
['gltf_anim_scene_split_object'] = False
1014 export_settings
['gltf_nla_strips_merged_animation_name'] = self
.export_nla_strips_merged_animation_name
1015 export_settings
['gltf_optimize_animation'] = self
.export_optimize_animation_size
1016 export_settings
['gltf_optimize_animation_keep_armature'] = self
.export_optimize_animation_keep_anim_armature
1017 export_settings
['gltf_optimize_animation_keep_object'] = self
.export_optimize_animation_keep_anim_object
1018 export_settings
['gltf_export_anim_single_armature'] = self
.export_anim_single_armature
1019 export_settings
['gltf_export_reset_pose_bones'] = self
.export_reset_pose_bones
1020 export_settings
['gltf_export_reset_sk_data'] = self
.export_morph_reset_sk_data
1021 export_settings
['gltf_bake_animation'] = self
.export_bake_animation
1022 export_settings
['gltf_negative_frames'] = self
.export_negative_frame
1023 export_settings
['gltf_anim_slide_to_zero'] = self
.export_anim_slide_to_zero
1025 export_settings
['gltf_frame_range'] = False
1026 export_settings
['gltf_force_sampling'] = False
1027 export_settings
['gltf_bake_animation'] = False
1028 export_settings
['gltf_optimize_animation'] = False
1029 export_settings
['gltf_optimize_animation_keep_armature'] = False
1030 export_settings
['gltf_optimize_animation_keep_object'] = False
1031 export_settings
['gltf_export_anim_single_armature'] = False
1032 export_settings
['gltf_export_reset_pose_bones'] = False
1033 export_settings
['gltf_export_reset_sk_data'] = False
1034 export_settings
['gltf_skins'] = self
.export_skins
1035 if self
.export_skins
:
1036 export_settings
['gltf_all_vertex_influences'] = self
.export_all_influences
1037 export_settings
['gltf_vertex_influences_nb'] = self
.export_influence_nb
1039 export_settings
['gltf_all_vertex_influences'] = False
1040 export_settings
['gltf_def_bones'] = False
1041 export_settings
['gltf_rest_position_armature'] = self
.export_rest_position_armature
1042 export_settings
['gltf_frame_step'] = self
.export_frame_step
1044 export_settings
['gltf_morph'] = self
.export_morph
1045 if self
.export_morph
:
1046 export_settings
['gltf_morph_normal'] = self
.export_morph_normal
1047 export_settings
['gltf_morph_tangent'] = self
.export_morph_tangent
1048 export_settings
['gltf_morph_anim'] = self
.export_morph_animation
1050 export_settings
['gltf_morph_normal'] = False
1051 export_settings
['gltf_morph_tangent'] = False
1052 export_settings
['gltf_morph_anim'] = False
1054 export_settings
['gltf_lights'] = self
.export_lights
1055 export_settings
['gltf_lighting_mode'] = self
.export_import_convert_lighting_mode
1056 export_settings
['gltf_gpu_instances'] = self
.export_gpu_instances
1058 export_settings
['gltf_try_sparse_sk'] = self
.export_try_sparse_sk
1059 export_settings
['gltf_try_omit_sparse_sk'] = self
.export_try_omit_sparse_sk
1060 if not self
.export_try_sparse_sk
:
1061 export_settings
['gltf_try_omit_sparse_sk'] = False
1063 export_settings
['gltf_hierarchy_full_collections'] = self
.export_hierarchy_full_collections
1066 export_settings
['gltf_use_gltfpack'] = self
.export_use_gltfpack
1067 if self
.export_use_gltfpack
:
1068 export_settings
['gltf_gltfpack_tc'] = self
.export_gltfpack_tc
1069 export_settings
['gltf_gltfpack_tq'] = self
.export_gltfpack_tq
1071 export_settings
['gltf_gltfpack_si'] = self
.export_gltfpack_si
1072 export_settings
['gltf_gltfpack_sa'] = self
.export_gltfpack_sa
1073 export_settings
['gltf_gltfpack_slb'] = self
.export_gltfpack_slb
1075 export_settings
['gltf_gltfpack_vp'] = self
.export_gltfpack_vp
1076 export_settings
['gltf_gltfpack_vt'] = self
.export_gltfpack_vt
1077 export_settings
['gltf_gltfpack_vn'] = self
.export_gltfpack_vn
1078 export_settings
['gltf_gltfpack_vc'] = self
.export_gltfpack_vc
1080 export_settings
['gltf_gltfpack_vpi'] = self
.export_gltfpack_vpi
1082 export_settings
['gltf_gltfpack_noq'] = self
.export_gltfpack_noq
1084 export_settings
['gltf_binary'] = bytearray()
1085 export_settings
['gltf_binaryfilename'] = (
1086 path_to_uri(os
.path
.splitext(os
.path
.basename(self
.filepath
))[0] + '.bin')
1089 user_extensions
= []
1090 pre_export_callbacks
= []
1091 post_export_callbacks
= []
1094 preferences
= bpy
.context
.preferences
1095 for addon_name
in preferences
.addons
.keys():
1097 module
= sys
.modules
[addon_name
]
1100 if hasattr(module
, 'glTF2ExportUserExtension'):
1101 extension_ctor
= module
.glTF2ExportUserExtension
1102 user_extensions
.append(extension_ctor())
1103 if hasattr(module
, 'glTF2ExportUserExtensions'):
1104 extension_ctors
= module
.glTF2ExportUserExtensions
1105 for extension_ctor
in extension_ctors
:
1106 user_extensions
.append(extension_ctor())
1107 if hasattr(module
, 'glTF2_pre_export_callback'):
1108 pre_export_callbacks
.append(module
.glTF2_pre_export_callback
)
1109 if hasattr(module
, 'glTF2_post_export_callback'):
1110 post_export_callbacks
.append(module
.glTF2_post_export_callback
)
1111 export_settings
['gltf_user_extensions'] = user_extensions
1112 export_settings
['pre_export_callbacks'] = pre_export_callbacks
1113 export_settings
['post_export_callbacks'] = post_export_callbacks
1115 return gltf2_blender_export
.save(context
, export_settings
)
1117 def draw(self
, context
):
1118 pass # Is needed to get panels available
1121 class GLTF_PT_export_main(bpy
.types
.Panel
):
1122 bl_space_type
= 'FILE_BROWSER'
1123 bl_region_type
= 'TOOL_PROPS'
1125 bl_parent_id
= "FILE_PT_operator"
1126 bl_options
= {'HIDE_HEADER'}
1129 def poll(cls
, context
):
1130 sfile
= context
.space_data
1131 operator
= sfile
.active_operator
1133 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1135 def draw(self
, context
):
1136 layout
= self
.layout
1137 layout
.use_property_split
= True
1138 layout
.use_property_decorate
= False # No animation.
1140 sfile
= context
.space_data
1141 operator
= sfile
.active_operator
1143 layout
.prop(operator
, 'export_format')
1144 if operator
.export_format
== 'GLTF_SEPARATE':
1145 layout
.prop(operator
, 'export_keep_originals')
1146 if operator
.export_keep_originals
is False:
1147 layout
.prop(operator
, 'export_texture_dir', icon
='FILE_FOLDER')
1149 layout
.prop(operator
, 'export_copyright')
1150 layout
.prop(operator
, 'will_save_settings')
1153 class GLTF_PT_export_gltfpack(bpy
.types
.Panel
):
1154 bl_space_type
= 'FILE_BROWSER'
1155 bl_region_type
= 'TOOL_PROPS'
1156 bl_label
= "gltfpack"
1157 bl_parent_id
= "FILE_PT_operator"
1158 bl_options
= {'DEFAULT_CLOSED'}
1161 def poll(cls
, context
):
1162 gltfpack_path
= context
.preferences
.addons
['io_scene_gltf2'].preferences
.gltfpack_path_ui
.strip()
1163 if (gltfpack_path
== ''): # gltfpack not setup in plugin preferences -> dont show any gltfpack relevant options in export dialog
1166 sfile
= context
.space_data
1167 operator
= sfile
.active_operator
1169 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1171 def draw(self
, context
):
1173 layout
= self
.layout
1174 layout
.use_property_split
= True
1175 layout
.use_property_decorate
= False # No animation.
1177 sfile
= context
.space_data
1178 operator
= sfile
.active_operator
1180 col
= layout
.column(heading
= "gltfpack", align
= True)
1181 col
.prop(operator
, 'export_use_gltfpack')
1183 col
= layout
.column(heading
= "Textures", align
= True)
1184 col
.prop(operator
, 'export_gltfpack_tc')
1185 col
.prop(operator
, 'export_gltfpack_tq')
1186 col
= layout
.column(heading
= "Simplification", align
= True)
1187 col
.prop(operator
, 'export_gltfpack_si')
1188 col
.prop(operator
, 'export_gltfpack_sa')
1189 col
.prop(operator
, 'export_gltfpack_slb')
1190 col
= layout
.column(heading
= "Vertices", align
= True)
1191 col
.prop(operator
, 'export_gltfpack_vp')
1192 col
.prop(operator
, 'export_gltfpack_vt')
1193 col
.prop(operator
, 'export_gltfpack_vn')
1194 col
.prop(operator
, 'export_gltfpack_vc')
1195 col
= layout
.column(heading
= "Vertex positions", align
= True)
1196 col
.prop(operator
, 'export_gltfpack_vpi')
1197 #col = layout.column(heading = "Animations", align = True)
1198 #col = layout.column(heading = "Scene", align = True)
1199 col
= layout
.column(heading
= "Miscellaneous", align
= True)
1200 col
.prop(operator
, 'export_gltfpack_noq')
1203 class GLTF_PT_export_include(bpy
.types
.Panel
):
1204 bl_space_type
= 'FILE_BROWSER'
1205 bl_region_type
= 'TOOL_PROPS'
1206 bl_label
= "Include"
1207 bl_parent_id
= "FILE_PT_operator"
1208 bl_options
= {'DEFAULT_CLOSED'}
1211 def poll(cls
, context
):
1212 sfile
= context
.space_data
1213 operator
= sfile
.active_operator
1215 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1217 def draw(self
, context
):
1218 layout
= self
.layout
1219 layout
.use_property_split
= True
1220 layout
.use_property_decorate
= False # No animation.
1222 sfile
= context
.space_data
1223 operator
= sfile
.active_operator
1225 col
= layout
.column(heading
= "Limit to", align
= True)
1226 col
.prop(operator
, 'use_selection')
1227 col
.prop(operator
, 'use_visible')
1228 col
.prop(operator
, 'use_renderable')
1229 col
.prop(operator
, 'use_active_collection')
1230 if operator
.use_active_collection
:
1231 col
.prop(operator
, 'use_active_collection_with_nested')
1232 col
.prop(operator
, 'use_active_scene')
1234 col
= layout
.column(heading
= "Data", align
= True)
1235 col
.prop(operator
, 'export_extras')
1236 col
.prop(operator
, 'export_cameras')
1237 col
.prop(operator
, 'export_lights')
1240 class GLTF_PT_export_transform(bpy
.types
.Panel
):
1241 bl_space_type
= 'FILE_BROWSER'
1242 bl_region_type
= 'TOOL_PROPS'
1243 bl_label
= "Transform"
1244 bl_parent_id
= "FILE_PT_operator"
1245 bl_options
= {'DEFAULT_CLOSED'}
1248 def poll(cls
, context
):
1249 sfile
= context
.space_data
1250 operator
= sfile
.active_operator
1252 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1254 def draw(self
, context
):
1255 layout
= self
.layout
1256 layout
.use_property_split
= True
1257 layout
.use_property_decorate
= False # No animation.
1259 sfile
= context
.space_data
1260 operator
= sfile
.active_operator
1262 layout
.prop(operator
, 'export_yup')
1265 class GLTF_PT_export_data(bpy
.types
.Panel
):
1266 bl_space_type
= 'FILE_BROWSER'
1267 bl_region_type
= 'TOOL_PROPS'
1269 bl_parent_id
= "FILE_PT_operator"
1270 bl_options
= {'DEFAULT_CLOSED'}
1273 def poll(cls
, context
):
1274 sfile
= context
.space_data
1275 operator
= sfile
.active_operator
1277 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1279 def draw(self
, context
):
1282 class GLTF_PT_export_data_scene(bpy
.types
.Panel
):
1283 bl_space_type
= 'FILE_BROWSER'
1284 bl_region_type
= 'TOOL_PROPS'
1285 bl_label
= "Scene Graph"
1286 bl_parent_id
= "GLTF_PT_export_data"
1287 bl_options
= {'DEFAULT_CLOSED'}
1290 def poll(cls
, context
):
1291 sfile
= context
.space_data
1292 operator
= sfile
.active_operator
1293 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1295 def draw(self
, context
):
1296 layout
= self
.layout
1297 layout
.use_property_split
= True
1298 layout
.use_property_decorate
= False # No animation.
1300 sfile
= context
.space_data
1301 operator
= sfile
.active_operator
1302 layout
.prop(operator
, 'export_gn_mesh')
1303 layout
.prop(operator
, 'export_gpu_instances')
1304 layout
.prop(operator
, 'export_hierarchy_flatten_objs')
1305 layout
.prop(operator
, 'export_hierarchy_full_collections')
1307 class GLTF_PT_export_data_mesh(bpy
.types
.Panel
):
1308 bl_space_type
= 'FILE_BROWSER'
1309 bl_region_type
= 'TOOL_PROPS'
1311 bl_parent_id
= "GLTF_PT_export_data"
1312 bl_options
= {'DEFAULT_CLOSED'}
1315 def poll(cls
, context
):
1316 sfile
= context
.space_data
1317 operator
= sfile
.active_operator
1318 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1320 def draw(self
, context
):
1321 layout
= self
.layout
1322 layout
.use_property_split
= True
1323 layout
.use_property_decorate
= False # No animation.
1325 sfile
= context
.space_data
1326 operator
= sfile
.active_operator
1328 layout
.prop(operator
, 'export_apply')
1329 layout
.prop(operator
, 'export_texcoords')
1330 layout
.prop(operator
, 'export_normals')
1331 col
= layout
.column()
1332 col
.active
= operator
.export_normals
1333 col
.prop(operator
, 'export_tangents')
1334 layout
.prop(operator
, 'export_attributes')
1336 col
= layout
.column()
1337 col
.prop(operator
, 'use_mesh_edges')
1338 col
.prop(operator
, 'use_mesh_vertices')
1340 col
= layout
.column()
1341 col
.prop(operator
, 'export_shared_accessors')
1344 class GLTF_PT_export_data_material(bpy
.types
.Panel
):
1345 bl_space_type
= 'FILE_BROWSER'
1346 bl_region_type
= 'TOOL_PROPS'
1347 bl_label
= "Material"
1348 bl_parent_id
= "GLTF_PT_export_data"
1349 bl_options
= {'DEFAULT_CLOSED'}
1352 def poll(cls
, context
):
1353 sfile
= context
.space_data
1354 operator
= sfile
.active_operator
1355 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1357 def draw(self
, context
):
1358 layout
= self
.layout
1359 layout
.use_property_split
= True
1360 layout
.use_property_decorate
= False # No animation.
1362 sfile
= context
.space_data
1363 operator
= sfile
.active_operator
1365 layout
.prop(operator
, 'export_materials')
1366 col
= layout
.column()
1367 col
.active
= operator
.export_materials
== "EXPORT"
1368 col
.prop(operator
, 'export_image_format')
1369 if operator
.export_image_format
in ["AUTO", "JPEG", "WEBP"]:
1370 col
.prop(operator
, 'export_image_quality')
1371 col
= layout
.column()
1372 col
.active
= operator
.export_image_format
!= "WEBP"
1373 col
.prop(operator
, "export_image_add_webp")
1374 col
= layout
.column()
1375 col
.active
= operator
.export_image_format
!= "WEBP"
1376 col
.prop(operator
, "export_image_webp_fallback")
1378 class GLTF_PT_export_unsed_tex_image(bpy
.types
.Panel
):
1379 bl_space_type
= 'FILE_BROWSER'
1380 bl_region_type
= 'TOOL_PROPS'
1381 bl_label
= "Unused Textures & Images"
1382 bl_parent_id
= "GLTF_PT_export_data_material"
1383 bl_options
= {'DEFAULT_CLOSED'}
1386 def poll(cls
, context
):
1387 sfile
= context
.space_data
1388 operator
= sfile
.active_operator
1390 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1392 def draw(self
, context
):
1393 layout
= self
.layout
1394 layout
.use_property_split
= True
1395 layout
.use_property_decorate
= False # No animation.
1397 sfile
= context
.space_data
1398 operator
= sfile
.active_operator
1401 row
.prop(operator
, 'export_unused_images')
1403 row
.prop(operator
, 'export_unused_textures')
1406 class GLTF_PT_export_data_lighting(bpy
.types
.Panel
):
1407 bl_space_type
= 'FILE_BROWSER'
1408 bl_region_type
= 'TOOL_PROPS'
1409 bl_label
= "Lighting"
1410 bl_parent_id
= "GLTF_PT_export_data"
1411 bl_options
= {'DEFAULT_CLOSED'}
1414 def poll(cls
, context
):
1415 sfile
= context
.space_data
1416 operator
= sfile
.active_operator
1417 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1419 def draw(self
, context
):
1420 layout
= self
.layout
1421 layout
.use_property_split
= True
1422 layout
.use_property_decorate
= False # No animation.
1424 sfile
= context
.space_data
1425 operator
= sfile
.active_operator
1427 layout
.prop(operator
, 'export_import_convert_lighting_mode')
1429 class GLTF_PT_export_data_shapekeys(bpy
.types
.Panel
):
1430 bl_space_type
= 'FILE_BROWSER'
1431 bl_region_type
= 'TOOL_PROPS'
1432 bl_label
= "Shape Keys"
1433 bl_parent_id
= "GLTF_PT_export_data"
1434 bl_options
= {'DEFAULT_CLOSED'}
1437 def poll(cls
, context
):
1438 sfile
= context
.space_data
1439 operator
= sfile
.active_operator
1441 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1443 def draw_header(self
, context
):
1444 sfile
= context
.space_data
1445 operator
= sfile
.active_operator
1446 self
.layout
.prop(operator
, "export_morph", text
="")
1448 def draw(self
, context
):
1449 layout
= self
.layout
1450 layout
.use_property_split
= True
1451 layout
.use_property_decorate
= False # No animation.
1453 sfile
= context
.space_data
1454 operator
= sfile
.active_operator
1456 layout
.active
= operator
.export_morph
1458 layout
.prop(operator
, 'export_morph_normal')
1459 col
= layout
.column()
1460 col
.active
= operator
.export_morph_normal
1461 col
.prop(operator
, 'export_morph_tangent')
1464 class GLTF_PT_export_data_sk_optimize(bpy
.types
.Panel
):
1465 bl_space_type
= 'FILE_BROWSER'
1466 bl_region_type
= 'TOOL_PROPS'
1467 bl_label
= "Optimize Shape Keys"
1468 bl_parent_id
= "GLTF_PT_export_data_shapekeys"
1469 bl_options
= {'DEFAULT_CLOSED'}
1472 def poll(cls
, context
):
1473 sfile
= context
.space_data
1474 operator
= sfile
.active_operator
1476 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1478 def draw(self
, context
):
1479 layout
= self
.layout
1480 layout
.use_property_split
= True
1481 layout
.use_property_decorate
= False # No animation.
1483 sfile
= context
.space_data
1484 operator
= sfile
.active_operator
1487 row
.prop(operator
, 'export_try_sparse_sk')
1490 row
.active
= operator
.export_try_sparse_sk
1491 row
.prop(operator
, 'export_try_omit_sparse_sk')
1494 class GLTF_PT_export_data_skinning(bpy
.types
.Panel
):
1495 bl_space_type
= 'FILE_BROWSER'
1496 bl_region_type
= 'TOOL_PROPS'
1497 bl_label
= "Skinning"
1498 bl_parent_id
= "GLTF_PT_export_data"
1499 bl_options
= {'DEFAULT_CLOSED'}
1502 def poll(cls
, context
):
1503 sfile
= context
.space_data
1504 operator
= sfile
.active_operator
1506 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1508 def draw_header(self
, context
):
1509 sfile
= context
.space_data
1510 operator
= sfile
.active_operator
1511 self
.layout
.prop(operator
, "export_skins", text
="")
1513 def draw(self
, context
):
1514 layout
= self
.layout
1515 layout
.use_property_split
= True
1516 layout
.use_property_decorate
= False # No animation.
1518 sfile
= context
.space_data
1519 operator
= sfile
.active_operator
1521 layout
.active
= operator
.export_skins
1524 row
.prop(operator
, 'export_influence_nb')
1525 row
.active
= not operator
.export_all_influences
1526 layout
.prop(operator
, 'export_all_influences')
1529 class GLTF_PT_export_data_armature(bpy
.types
.Panel
):
1530 bl_space_type
= 'FILE_BROWSER'
1531 bl_region_type
= 'TOOL_PROPS'
1532 bl_label
= "Armature"
1533 bl_parent_id
= "GLTF_PT_export_data"
1534 bl_options
= {'DEFAULT_CLOSED'}
1537 def poll(cls
, context
):
1538 sfile
= context
.space_data
1539 operator
= sfile
.active_operator
1541 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1543 def draw(self
, context
):
1544 layout
= self
.layout
1545 layout
.use_property_split
= True
1546 layout
.use_property_decorate
= False # No animation.
1548 sfile
= context
.space_data
1549 operator
= sfile
.active_operator
1551 layout
.active
= operator
.export_skins
1553 layout
.prop(operator
, 'export_rest_position_armature')
1556 row
.active
= operator
.export_force_sampling
1557 row
.prop(operator
, 'export_def_bones')
1558 if operator
.export_force_sampling
is False and operator
.export_def_bones
is True:
1559 layout
.label(text
="Export only deformation bones is not possible when not sampling animation")
1561 row
.prop(operator
, 'export_armature_object_remove')
1563 row
.prop(operator
, 'export_hierarchy_flatten_bones')
1565 class GLTF_PT_export_data_compression(bpy
.types
.Panel
):
1566 bl_space_type
= 'FILE_BROWSER'
1567 bl_region_type
= 'TOOL_PROPS'
1568 bl_label
= "Compression"
1569 bl_parent_id
= "GLTF_PT_export_data"
1570 bl_options
= {'DEFAULT_CLOSED'}
1573 from .io
.com
import gltf2_io_draco_compression_extension
1574 self
.is_draco_available
= gltf2_io_draco_compression_extension
.dll_exists(quiet
=True)
1577 def poll(cls
, context
):
1578 sfile
= context
.space_data
1579 operator
= sfile
.active_operator
1580 if operator
.is_draco_available
:
1581 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1583 def draw_header(self
, context
):
1584 sfile
= context
.space_data
1585 operator
= sfile
.active_operator
1586 self
.layout
.prop(operator
, "export_draco_mesh_compression_enable", text
="")
1588 def draw(self
, context
):
1589 layout
= self
.layout
1590 layout
.use_property_split
= True
1591 layout
.use_property_decorate
= False # No animation.
1593 sfile
= context
.space_data
1594 operator
= sfile
.active_operator
1596 layout
.active
= operator
.export_draco_mesh_compression_enable
1597 layout
.prop(operator
, 'export_draco_mesh_compression_level')
1599 col
= layout
.column(align
=True)
1600 col
.prop(operator
, 'export_draco_position_quantization', text
="Quantize Position")
1601 col
.prop(operator
, 'export_draco_normal_quantization', text
="Normal")
1602 col
.prop(operator
, 'export_draco_texcoord_quantization', text
="Tex Coord")
1603 col
.prop(operator
, 'export_draco_color_quantization', text
="Color")
1604 col
.prop(operator
, 'export_draco_generic_quantization', text
="Generic")
1607 class GLTF_PT_export_animation(bpy
.types
.Panel
):
1608 bl_space_type
= 'FILE_BROWSER'
1609 bl_region_type
= 'TOOL_PROPS'
1610 bl_label
= "Animation"
1611 bl_parent_id
= "FILE_PT_operator"
1612 bl_options
= {'DEFAULT_CLOSED'}
1615 def poll(cls
, context
):
1616 sfile
= context
.space_data
1617 operator
= sfile
.active_operator
1619 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1621 def draw_header(self
, context
):
1622 sfile
= context
.space_data
1623 operator
= sfile
.active_operator
1624 self
.layout
.prop(operator
, "export_animations", text
="")
1626 def draw(self
, context
):
1627 layout
= self
.layout
1628 layout
.use_property_split
= True
1629 layout
.use_property_decorate
= False # No animation.
1631 sfile
= context
.space_data
1632 operator
= sfile
.active_operator
1634 layout
.active
= operator
.export_animations
1636 layout
.prop(operator
, 'export_animation_mode')
1637 if operator
.export_animation_mode
== "ACTIVE_ACTIONS":
1638 layout
.prop(operator
, 'export_nla_strips_merged_animation_name')
1641 row
.active
= operator
.export_force_sampling
and operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS']
1642 row
.prop(operator
, 'export_bake_animation')
1643 if operator
.export_animation_mode
== "SCENE":
1644 layout
.prop(operator
, 'export_anim_scene_split_object')
1646 class GLTF_PT_export_animation_notes(bpy
.types
.Panel
):
1647 bl_space_type
= 'FILE_BROWSER'
1648 bl_region_type
= 'TOOL_PROPS'
1650 bl_parent_id
= "GLTF_PT_export_animation"
1651 bl_options
= {'DEFAULT_CLOSED'}
1654 def poll(cls
, context
):
1655 sfile
= context
.space_data
1656 operator
= sfile
.active_operator
1658 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf" and \
1659 operator
.export_animation_mode
in ["NLA_TRACKS", "SCENE"]
1661 def draw(self
, context
):
1662 operator
= context
.space_data
.active_operator
1663 layout
= self
.layout
1664 if operator
.export_animation_mode
== "SCENE":
1665 layout
.label(text
="Scene mode uses full bake mode:")
1666 layout
.label(text
="- sampling is active")
1667 layout
.label(text
="- baking all objects is active")
1668 layout
.label(text
="- Using scene frame range")
1669 elif operator
.export_animation_mode
== "NLA_TRACKS":
1670 layout
.label(text
="Track mode uses full bake mode:")
1671 layout
.label(text
="- sampling is active")
1672 layout
.label(text
="- baking all objects is active")
1674 class GLTF_PT_export_animation_ranges(bpy
.types
.Panel
):
1675 bl_space_type
= 'FILE_BROWSER'
1676 bl_region_type
= 'TOOL_PROPS'
1677 bl_label
= "Rest & Ranges"
1678 bl_parent_id
= "GLTF_PT_export_animation"
1679 bl_options
= {'DEFAULT_CLOSED'}
1682 def poll(cls
, context
):
1683 sfile
= context
.space_data
1684 operator
= sfile
.active_operator
1686 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1688 def draw(self
, context
):
1689 layout
= self
.layout
1690 layout
.use_property_split
= True
1691 layout
.use_property_decorate
= False # No animation.
1693 sfile
= context
.space_data
1694 operator
= sfile
.active_operator
1696 layout
.active
= operator
.export_animations
1698 layout
.prop(operator
, 'export_current_frame')
1700 row
.active
= operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS', 'NLA_TRACKS']
1701 row
.prop(operator
, 'export_frame_range')
1702 layout
.prop(operator
, 'export_anim_slide_to_zero')
1704 row
.active
= operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS', 'NLA_TRACKS']
1705 layout
.prop(operator
, 'export_negative_frame')
1707 class GLTF_PT_export_animation_armature(bpy
.types
.Panel
):
1708 bl_space_type
= 'FILE_BROWSER'
1709 bl_region_type
= 'TOOL_PROPS'
1710 bl_label
= "Armature"
1711 bl_parent_id
= "GLTF_PT_export_animation"
1712 bl_options
= {'DEFAULT_CLOSED'}
1715 def poll(cls
, context
):
1716 sfile
= context
.space_data
1717 operator
= sfile
.active_operator
1719 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1721 def draw(self
, context
):
1722 layout
= self
.layout
1723 layout
.use_property_split
= True
1724 layout
.use_property_decorate
= False # No animation.
1726 sfile
= context
.space_data
1727 operator
= sfile
.active_operator
1729 layout
.active
= operator
.export_animations
1731 layout
.prop(operator
, 'export_anim_single_armature')
1732 layout
.prop(operator
, 'export_reset_pose_bones')
1734 class GLTF_PT_export_animation_shapekeys(bpy
.types
.Panel
):
1735 bl_space_type
= 'FILE_BROWSER'
1736 bl_region_type
= 'TOOL_PROPS'
1737 bl_label
= "Shape Keys Animation"
1738 bl_parent_id
= "GLTF_PT_export_animation"
1739 bl_options
= {'DEFAULT_CLOSED'}
1742 def poll(cls
, context
):
1743 sfile
= context
.space_data
1744 operator
= sfile
.active_operator
1746 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1748 def draw_header(self
, context
):
1749 sfile
= context
.space_data
1750 operator
= sfile
.active_operator
1751 self
.layout
.active
= operator
.export_animations
and operator
.export_morph
1752 self
.layout
.prop(operator
, "export_morph_animation", text
="")
1754 def draw(self
, context
):
1755 layout
= self
.layout
1756 layout
.use_property_split
= True
1757 layout
.use_property_decorate
= False # No animation.
1759 sfile
= context
.space_data
1760 operator
= sfile
.active_operator
1762 layout
.active
= operator
.export_animations
1764 layout
.prop(operator
, 'export_morph_reset_sk_data')
1767 class GLTF_PT_export_animation_sampling(bpy
.types
.Panel
):
1768 bl_space_type
= 'FILE_BROWSER'
1769 bl_region_type
= 'TOOL_PROPS'
1770 bl_label
= "Sampling Animations"
1771 bl_parent_id
= "GLTF_PT_export_animation"
1772 bl_options
= {'DEFAULT_CLOSED'}
1775 def poll(cls
, context
):
1776 sfile
= context
.space_data
1777 operator
= sfile
.active_operator
1779 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1781 def draw_header(self
, context
):
1782 sfile
= context
.space_data
1783 operator
= sfile
.active_operator
1784 self
.layout
.active
= operator
.export_animations
and operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS']
1785 self
.layout
.prop(operator
, "export_force_sampling", text
="")
1787 def draw(self
, context
):
1788 layout
= self
.layout
1789 layout
.use_property_split
= True
1790 layout
.use_property_decorate
= False # No animation.
1792 sfile
= context
.space_data
1793 operator
= sfile
.active_operator
1795 layout
.active
= operator
.export_animations
1797 layout
.prop(operator
, 'export_frame_step')
1800 class GLTF_PT_export_animation_optimize(bpy
.types
.Panel
):
1801 bl_space_type
= 'FILE_BROWSER'
1802 bl_region_type
= 'TOOL_PROPS'
1803 bl_label
= "Optimize Animations"
1804 bl_parent_id
= "GLTF_PT_export_animation"
1805 bl_options
= {'DEFAULT_CLOSED'}
1808 def poll(cls
, context
):
1809 sfile
= context
.space_data
1810 operator
= sfile
.active_operator
1812 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf"
1814 def draw(self
, context
):
1815 layout
= self
.layout
1816 layout
.use_property_split
= True
1817 layout
.use_property_decorate
= False # No animation.
1819 sfile
= context
.space_data
1820 operator
= sfile
.active_operator
1822 layout
.active
= operator
.export_animations
1824 layout
.prop(operator
, 'export_optimize_animation_size')
1827 row
.prop(operator
, 'export_optimize_animation_keep_anim_armature')
1830 row
.prop(operator
, 'export_optimize_animation_keep_anim_object')
1833 class GLTF_PT_export_user_extensions(bpy
.types
.Panel
):
1834 bl_space_type
= 'FILE_BROWSER'
1835 bl_region_type
= 'TOOL_PROPS'
1836 bl_label
= "Exporter Extensions"
1837 bl_parent_id
= "FILE_PT_operator"
1838 bl_options
= {'DEFAULT_CLOSED'}
1841 def poll(cls
, context
):
1842 sfile
= context
.space_data
1843 operator
= sfile
.active_operator
1845 return operator
.bl_idname
== "EXPORT_SCENE_OT_gltf" and operator
.has_active_exporter_extensions
1847 def draw(self
, context
):
1848 layout
= self
.layout
1849 layout
.use_property_split
= True
1850 layout
.use_property_decorate
= False # No animation.
1852 class GLTF_PT_import_user_extensions(bpy
.types
.Panel
):
1853 bl_space_type
= 'FILE_BROWSER'
1854 bl_region_type
= 'TOOL_PROPS'
1855 bl_label
= "Importer Extensions"
1856 bl_parent_id
= "FILE_PT_operator"
1857 bl_options
= {'DEFAULT_CLOSED'}
1860 def poll(cls
, context
):
1861 sfile
= context
.space_data
1862 operator
= sfile
.active_operator
1863 return operator
.bl_idname
== "IMPORT_SCENE_OT_gltf" and operator
.has_active_importer_extensions
1865 def draw(self
, context
):
1866 layout
= self
.layout
1867 layout
.use_property_split
= True
1868 layout
.use_property_decorate
= False # No animation.
1870 class ExportGLTF2(bpy
.types
.Operator
, ExportGLTF2_Base
, ExportHelper
):
1871 """Export scene as glTF 2.0 file"""
1872 bl_idname
= 'export_scene.gltf'
1873 bl_label
= 'Export glTF 2.0'
1877 filter_glob
: StringProperty(default
='*.glb', options
={'HIDDEN'})
1880 def menu_func_export(self
, context
):
1881 self
.layout
.operator(ExportGLTF2
.bl_idname
, text
='glTF 2.0 (.glb/.gltf)')
1884 class ImportGLTF2(Operator
, ConvertGLTF2_Base
, ImportHelper
):
1885 """Load a glTF 2.0 file"""
1886 bl_idname
= 'import_scene.gltf'
1887 bl_label
= 'Import glTF 2.0'
1888 bl_options
= {'REGISTER', 'UNDO'}
1890 filter_glob
: StringProperty(default
="*.glb;*.gltf", options
={'HIDDEN'})
1892 files
: CollectionProperty(
1894 type=bpy
.types
.OperatorFileListElement
,
1897 loglevel
: IntProperty(
1899 description
="Log Level")
1901 import_pack_images
: BoolProperty(
1903 description
='Pack all images into .blend file',
1907 merge_vertices
: BoolProperty(
1908 name
='Merge Vertices',
1910 'The glTF format requires discontinuous normals, UVs, and '
1911 'other vertex attributes to be stored as separate vertices, '
1912 'as required for rendering on typical graphics hardware. '
1913 'This option attempts to combine co-located vertices where possible. '
1914 'Currently cannot combine verts with different normals'
1919 import_shading
: EnumProperty(
1921 items
=(("NORMALS", "Use Normal Data", ""),
1922 ("FLAT", "Flat Shading", ""),
1923 ("SMOOTH", "Smooth Shading", "")),
1924 description
="How normals are computed during import",
1927 bone_heuristic
: EnumProperty(
1930 ("BLENDER", "Blender (best for import/export round trip)",
1931 "Good for re-importing glTFs exported from Blender, "
1932 "and re-exporting glTFs to glTFs after Blender editing. "
1933 "Bone tips are placed on their local +Y axis (in glTF space)"),
1934 ("TEMPERANCE", "Temperance (average)",
1935 "Decent all-around strategy. "
1936 "A bone with one child has its tip placed on the local axis "
1937 "closest to its child"),
1938 ("FORTUNE", "Fortune (may look better, less accurate)",
1939 "Might look better than Temperance, but also might have errors. "
1940 "A bone with one child has its tip placed at its child's root. "
1941 "Non-uniform scalings may get messed up though, so beware"),
1943 description
="Heuristic for placing bones. Tries to make bones pretty",
1947 guess_original_bind_pose
: BoolProperty(
1948 name
='Guess Original Bind Pose',
1950 'Try to guess the original bind pose for skinned meshes from '
1951 'the inverse bind matrices. '
1952 'When off, use default/rest pose as bind pose'
1957 import_webp_texture
: BoolProperty(
1958 name
='Import WebP textures',
1960 "If a texture exists in WebP format, "
1961 "loads the WebP texture instead of the fallback PNG/JPEG one"
1966 def draw(self
, context
):
1967 layout
= self
.layout
1969 layout
.use_property_split
= True
1970 layout
.use_property_decorate
= False # No animation.
1972 layout
.prop(self
, 'import_pack_images')
1973 layout
.prop(self
, 'merge_vertices')
1974 layout
.prop(self
, 'import_shading')
1975 layout
.prop(self
, 'guess_original_bind_pose')
1976 layout
.prop(self
, 'bone_heuristic')
1977 layout
.prop(self
, 'export_import_convert_lighting_mode')
1978 layout
.prop(self
, 'import_webp_texture')
1980 def invoke(self
, context
, event
):
1982 preferences
= bpy
.context
.preferences
1983 for addon_name
in preferences
.addons
.keys():
1985 if hasattr(sys
.modules
[addon_name
], 'glTF2ImportUserExtension') or hasattr(sys
.modules
[addon_name
], 'glTF2ImportUserExtensions'):
1986 importer_extension_panel_unregister_functors
.append(sys
.modules
[addon_name
].register_panel())
1990 self
.has_active_importer_extensions
= len(importer_extension_panel_unregister_functors
) > 0
1991 return ImportHelper
.invoke(self
, context
, event
)
1993 def execute(self
, context
):
1994 return self
.import_gltf2(context
)
1996 def import_gltf2(self
, context
):
1999 self
.set_debug_log()
2000 import_settings
= self
.as_keywords()
2002 user_extensions
= []
2005 preferences
= bpy
.context
.preferences
2006 for addon_name
in preferences
.addons
.keys():
2008 module
= sys
.modules
[addon_name
]
2011 if hasattr(module
, 'glTF2ImportUserExtension'):
2012 extension_ctor
= module
.glTF2ImportUserExtension
2013 user_extensions
.append(extension_ctor())
2014 import_settings
['import_user_extensions'] = user_extensions
2017 # Multiple file import
2019 dirname
= os
.path
.dirname(self
.filepath
)
2020 for file in self
.files
:
2021 path
= os
.path
.join(dirname
, file.name
)
2022 if self
.unit_import(path
, import_settings
) == {'FINISHED'}:
2026 # Single file import
2027 return self
.unit_import(self
.filepath
, import_settings
)
2029 def unit_import(self
, filename
, import_settings
):
2031 from .io
.imp
.gltf2_io_gltf
import glTFImporter
, ImportError
2032 from .blender
.imp
.gltf2_blender_gltf
import BlenderGlTF
2035 gltf_importer
= glTFImporter(filename
, import_settings
)
2036 gltf_importer
.read()
2037 gltf_importer
.checks()
2039 print("Data are loaded, start creating Blender stuff")
2041 start_time
= time
.time()
2042 BlenderGlTF
.create(gltf_importer
)
2043 elapsed_s
= "{:.2f}s".format(time
.time() - start_time
)
2044 print("glTF import finished in " + elapsed_s
)
2046 gltf_importer
.log
.removeHandler(gltf_importer
.log_handler
)
2050 except ImportError as e
:
2051 self
.report({'ERROR'}, e
.args
[0])
2052 return {'CANCELLED'}
2054 def set_debug_log(self
):
2056 if bpy
.app
.debug_value
== 0:
2057 self
.loglevel
= logging
.CRITICAL
2058 elif bpy
.app
.debug_value
== 1:
2059 self
.loglevel
= logging
.ERROR
2060 elif bpy
.app
.debug_value
== 2:
2061 self
.loglevel
= logging
.WARNING
2062 elif bpy
.app
.debug_value
== 3:
2063 self
.loglevel
= logging
.INFO
2065 self
.loglevel
= logging
.NOTSET
2068 class GLTF2_filter_action(bpy
.types
.PropertyGroup
):
2069 keep
: bpy
.props
.BoolProperty(name
="Keep Animation")
2070 action
: bpy
.props
.PointerProperty(type=bpy
.types
.Action
)
2072 def gltf_variant_ui_update(self
, context
):
2073 from .blender
.com
.gltf2_blender_ui
import variant_register
, variant_unregister
2074 if self
.KHR_materials_variants_ui
is True:
2075 # register all needed types
2078 variant_unregister()
2080 def gltf_animation_ui_update(self
, context
):
2081 from .blender
.com
.gltf2_blender_ui
import anim_ui_register
, anim_ui_unregister
2082 if self
.animation_ui
is True:
2083 # register all needed types
2086 anim_ui_unregister()
2088 class GLTF_AddonPreferences(bpy
.types
.AddonPreferences
):
2089 bl_idname
= __package__
2091 settings_node_ui
: bpy
.props
.BoolProperty(
2093 description
="Displays glTF Material Output node in Shader Editor (Menu Add > Output)"
2096 KHR_materials_variants_ui
: bpy
.props
.BoolProperty(
2098 description
="Displays glTF UI to manage material variants",
2099 update
=gltf_variant_ui_update
2102 animation_ui
: bpy
.props
.BoolProperty(
2104 description
="Display glTF UI to manage animations",
2105 update
=gltf_animation_ui_update
2108 gltfpack_path_ui
: bpy
.props
.StringProperty(
2110 name
="glTFpack file path",
2111 description
="Path to gltfpack binary",
2115 def draw(self
, context
):
2116 layout
= self
.layout
2118 row
.prop(self
, "settings_node_ui", text
="Shader Editor Add-ons")
2119 row
.prop(self
, "KHR_materials_variants_ui", text
="Material Variants")
2120 row
.prop(self
, "animation_ui", text
="Animation UI")
2122 row
.prop(self
, "gltfpack_path_ui", text
="Path to gltfpack")
2124 def menu_func_import(self
, context
):
2125 self
.layout
.operator(ImportGLTF2
.bl_idname
, text
='glTF 2.0 (.glb/.gltf)')
2130 GLTF_PT_export_main
,
2131 GLTF_PT_export_include
,
2132 GLTF_PT_export_transform
,
2133 GLTF_PT_export_data
,
2134 GLTF_PT_export_data_scene
,
2135 GLTF_PT_export_data_mesh
,
2136 GLTF_PT_export_data_material
,
2137 GLTF_PT_export_unsed_tex_image
,
2138 GLTF_PT_export_data_shapekeys
,
2139 GLTF_PT_export_data_sk_optimize
,
2140 GLTF_PT_export_data_armature
,
2141 GLTF_PT_export_data_skinning
,
2142 GLTF_PT_export_data_lighting
,
2143 GLTF_PT_export_data_compression
,
2144 GLTF_PT_export_animation
,
2145 GLTF_PT_export_animation_notes
,
2146 GLTF_PT_export_animation_ranges
,
2147 GLTF_PT_export_animation_armature
,
2148 GLTF_PT_export_animation_shapekeys
,
2149 GLTF_PT_export_animation_sampling
,
2150 GLTF_PT_export_animation_optimize
,
2151 GLTF_PT_export_gltfpack
,
2152 GLTF_PT_export_user_extensions
,
2154 GLTF_PT_import_user_extensions
,
2155 GLTF2_filter_action
,
2156 GLTF_AddonPreferences
2161 from .blender
.com
import gltf2_blender_ui
as blender_ui
2164 bpy
.utils
.register_class(c
)
2165 # bpy.utils.register_module(__name__)
2167 blender_ui
.register()
2168 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.KHR_materials_variants_ui
is True:
2169 blender_ui
.variant_register()
2170 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.animation_ui
is True:
2171 blender_ui
.anim_ui_register()
2173 # add to the export / import menu
2174 bpy
.types
.TOPBAR_MT_file_export
.append(menu_func_export
)
2175 bpy
.types
.TOPBAR_MT_file_import
.append(menu_func_import
)
2179 from .blender
.com
import gltf2_blender_ui
as blender_ui
2180 blender_ui
.unregister()
2181 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.KHR_materials_variants_ui
is True:
2182 blender_ui
.variant_unregister()
2185 bpy
.utils
.unregister_class(c
)
2186 for f
in exporter_extension_panel_unregister_functors
:
2188 exporter_extension_panel_unregister_functors
.clear()
2190 for f
in importer_extension_panel_unregister_functors
:
2192 importer_extension_panel_unregister_functors
.clear()
2194 # bpy.utils.unregister_module(__name__)
2196 # remove from the export / import menu
2197 bpy
.types
.TOPBAR_MT_file_export
.remove(menu_func_export
)
2198 bpy
.types
.TOPBAR_MT_file_import
.remove(menu_func_import
)