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
, poll_file_object_drop
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
124 def get_format_items(scene
, context
):
127 items
= (('GLB', 'glTF Binary (.glb)',
128 'Exports a single file, with all data packed in binary form. '
129 'Most efficient and portable, but more difficult to edit later'),
130 ('GLTF_SEPARATE', 'glTF Separate (.gltf + .bin + textures)',
131 'Exports multiple files, with separate JSON, binary and texture data. '
132 'Easiest to edit later'))
134 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences \
135 and "allow_embedded_format" in bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences \
136 and bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
['allow_embedded_format']:
137 # At initialization, the preferences are not yet loaded
138 # The second line check is needed until the PR is merge in Blender, for github CI tests
139 items
+= (('GLTF_EMBEDDED', 'glTF Embedded (.gltf)',
140 'Exports a single file, with all data packed in JSON. '
141 'Less efficient than binary, but easier to edit later'
147 def is_draco_available():
148 # Initialize on first use
149 if not hasattr(is_draco_available
, "draco_exists"):
150 from .io
.com
import gltf2_io_draco_compression_extension
151 is_draco_available
.draco_exists
= gltf2_io_draco_compression_extension
.dll_exists()
153 return is_draco_available
.draco_exists
156 class ConvertGLTF2_Base
:
157 """Base class containing options that should be exposed during both import and export."""
159 export_import_convert_lighting_mode
: EnumProperty(
160 name
='Lighting Mode',
162 ('SPEC', 'Standard', 'Physically-based glTF lighting units (cd, lx, nt)'),
163 ('COMPAT', 'Unitless', 'Non-physical, unitless lighting. Useful when exposure controls are not available'),
164 ('RAW', 'Raw (Deprecated)', 'Blender lighting strengths with no conversion'),
166 description
='Optional backwards compatibility for non-standard render engines. Applies to lights',# TODO: and emissive materials',
170 class ExportGLTF2_Base(ConvertGLTF2_Base
):
171 # TODO: refactor to avoid boilerplate
173 bl_options
= {'PRESET'}
175 # Don't use export_ prefix here, I don't want it to be saved with other export settings
176 gltf_export_id
: StringProperty(
179 'Identifier of caller (in case of add-on calling this exporter). '
180 'Can be useful in case of Extension added by other add-ons'
185 # gltfpack properties
186 export_use_gltfpack
: BoolProperty(
188 description
='Use gltfpack to simplify the mesh and/or compress its textures',
192 export_gltfpack_tc
: BoolProperty(
193 name
='KTX2 Compression',
194 description
='Convert all textures to KTX2 with BasisU supercompression',
198 export_gltfpack_tq
: IntProperty(
199 name
='Texture Encoding Quality',
200 description
='Texture encoding quality',
206 export_gltfpack_si
: FloatProperty(
207 name
='Mesh Simplification Ratio',
208 description
='Simplify meshes targeting triangle count ratio',
214 export_gltfpack_sa
: BoolProperty(
215 name
='Aggressive Mesh Simplification',
216 description
='Aggressively simplify to the target ratio disregarding quality',
220 export_gltfpack_slb
: BoolProperty(
221 name
='Lock Mesh Border Vertices',
222 description
='Lock border vertices during simplification to avoid gaps on connected meshes',
226 export_gltfpack_vp
: IntProperty(
227 name
='Position Quantization',
228 description
='Use N-bit quantization for positions',
234 export_gltfpack_vt
: IntProperty(
235 name
='Texture Coordinate Quantization',
236 description
='Use N-bit quantization for texture coordinates',
242 export_gltfpack_vn
: IntProperty(
243 name
='Normal/Tangent Quantization',
244 description
='Use N-bit quantization for normals and tangents',
250 export_gltfpack_vc
: IntProperty(
251 name
='Vertex Color Quantization',
252 description
='Use N-bit quantization for colors',
258 export_gltfpack_vpi
: EnumProperty(
259 name
='Vertex Position Attributes',
260 description
='Type to use for vertex position attributes',
261 items
=(('Integer', 'Integer', 'Use integer attributes for positions'),
262 ('Normalized', 'Normalized', 'Use normalized attributes for positions'),
263 ('Floating-point', 'Floating-point', 'Use floating-point attributes for positions')),
267 export_gltfpack_noq
: BoolProperty(
268 name
='Disable Quantization',
269 description
='Disable quantization; produces much larger glTF files with no extensions',
273 # TODO: some stuff in Textures
279 # TODO: some stuff in Miscellaneous
281 export_format
: EnumProperty(
283 items
=get_format_items
,
285 'Output format. Binary is most efficient, '
286 'but JSON may be easier to edit later'
288 default
=0, #Warning => If you change the default, need to change the default filter too
289 update
=on_export_format_changed
,
292 ui_tab
: EnumProperty(
293 items
=(('GENERAL', "General", "General settings"),
294 ('MESHES', "Meshes", "Mesh settings"),
295 ('OBJECTS', "Objects", "Object settings"),
296 ('ANIMATION', "Animation", "Animation settings")),
298 description
="Export setting categories",
301 export_copyright
: StringProperty(
303 description
='Legal rights and conditions for the model',
307 export_image_format
: EnumProperty(
309 items
=(('AUTO', 'Automatic',
310 'Save PNGs as PNGs, JPEGs as JPEGs, WebPs as WebPs. '
311 'For other formats, use PNG'),
312 ('JPEG', 'JPEG Format (.jpg)',
313 'Save images as JPEGs. (Images that need alpha are saved as PNGs though.) '
314 'Be aware of a possible loss in quality'),
315 ('WEBP', 'WebP Format',
316 'Save images as WebPs as main image (no fallback)'),
318 'Don\'t export images'),
321 'Output format for images. PNG is lossless and generally preferred, but JPEG might be preferable for web '
322 'applications due to the smaller file size. Alternatively they can be omitted if they are not needed'
327 export_image_add_webp
: BoolProperty(
330 "Creates WebP textures for every texture. "
331 "For already WebP textures, nothing happens"
336 export_image_webp_fallback
: BoolProperty(
337 name
='WebP fallback',
339 "For all WebP textures, create a PNG fallback texture"
344 export_texture_dir
: StringProperty(
346 description
='Folder to place texture files in. Relative to the .gltf file',
350 # Keep for back compatibility
351 export_jpeg_quality
: IntProperty(
353 description
='Quality of JPEG export',
359 # Keep for back compatibility
360 export_image_quality
: IntProperty(
361 name
='Image quality',
362 description
='Quality of image export',
368 export_keep_originals
: BoolProperty(
369 name
='Keep original',
370 description
=('Keep original textures files if possible. '
371 'WARNING: if you use more than one texture, '
372 'where pbr standard requires only one, only one texture will be used. '
373 'This can lead to unexpected results'
378 export_texcoords
: BoolProperty(
380 description
='Export UVs (texture coordinates) with meshes',
384 export_normals
: BoolProperty(
386 description
='Export vertex normals with meshes',
390 export_gn_mesh
: BoolProperty(
391 name
='Geometry Nodes Instances (Experimental)',
392 description
='Export Geometry nodes instance meshes',
396 export_draco_mesh_compression_enable
: BoolProperty(
397 name
='Draco mesh compression',
398 description
='Compress mesh using Draco',
402 export_draco_mesh_compression_level
: IntProperty(
403 name
='Compression level',
404 description
='Compression level (0 = most speed, 6 = most compression, higher values currently not supported)',
410 export_draco_position_quantization
: IntProperty(
411 name
='Position quantization bits',
412 description
='Quantization bits for position values (0 = no quantization)',
418 export_draco_normal_quantization
: IntProperty(
419 name
='Normal quantization bits',
420 description
='Quantization bits for normal values (0 = no quantization)',
426 export_draco_texcoord_quantization
: IntProperty(
427 name
='Texcoord quantization bits',
428 description
='Quantization bits for texture coordinate values (0 = no quantization)',
434 export_draco_color_quantization
: IntProperty(
435 name
='Color quantization bits',
436 description
='Quantization bits for color values (0 = no quantization)',
442 export_draco_generic_quantization
: IntProperty(
443 name
='Generic quantization bits',
444 description
='Quantization bits for generic values like weights or joints (0 = no quantization)',
450 export_tangents
: BoolProperty(
452 description
='Export vertex tangents with meshes',
456 export_materials
: EnumProperty(
458 items
=(('EXPORT', 'Export',
459 'Export all materials used by included objects'),
460 ('PLACEHOLDER', 'Placeholder',
461 'Do not export materials, but write multiple primitive groups per mesh, keeping material slot information'),
462 ('NONE', 'No export',
463 'Do not export materials, and combine mesh primitive groups, losing material slot information')),
464 description
='Export materials',
468 export_unused_images
: BoolProperty(
469 name
='Unused images',
470 description
='Export images not assigned to any material',
473 export_unused_textures
: BoolProperty(
474 name
='Prepare Unused textures',
476 'Export image texture nodes not assigned to any material. '
477 'This feature is not standard and needs an external extension to be included in the glTF file'
481 export_colors
: BoolProperty(
483 description
='Keep for compatibility only',
487 export_attributes
: BoolProperty(
489 description
='Export Attributes (when starting with underscore)',
493 use_mesh_edges
: BoolProperty(
496 'Export loose edges as lines, using the material from the first material slot'
501 use_mesh_vertices
: BoolProperty(
504 'Export loose points as glTF points, using the material from the first material slot'
509 export_cameras
: BoolProperty(
511 description
='Export cameras',
515 use_selection
: BoolProperty(
516 name
='Selected Objects',
517 description
='Export selected objects only',
521 use_visible
: BoolProperty(
522 name
='Visible Objects',
523 description
='Export visible objects only',
527 use_renderable
: BoolProperty(
528 name
='Renderable Objects',
529 description
='Export renderable objects only',
533 use_active_collection_with_nested
: BoolProperty(
534 name
='Include Nested Collections',
535 description
='Include active collection and nested collections',
539 use_active_collection
: BoolProperty(
540 name
='Active Collection',
541 description
='Export objects in the active collection only',
545 use_active_scene
: BoolProperty(
547 description
='Export active scene only',
551 collection
: StringProperty(
552 name
="Source Collection",
553 description
="Export only objects from this collection (and its children)",
557 export_extras
: BoolProperty(
558 name
='Custom Properties',
559 description
='Export custom properties as glTF extras',
563 export_yup
: BoolProperty(
565 description
='Export using glTF convention, +Y up',
569 export_apply
: BoolProperty(
570 name
='Apply Modifiers',
571 description
='Apply modifiers (excluding Armatures) to mesh objects -'
572 'WARNING: prevents exporting shape keys',
576 export_shared_accessors
: BoolProperty(
577 name
='Shared Accessors',
578 description
='Export Primitives using shared accessors for attributes',
582 export_animations
: BoolProperty(
584 description
='Exports active actions and NLA tracks as glTF animations',
588 export_frame_range
: BoolProperty(
589 name
='Limit to Playback Range',
590 description
='Clips animations to selected playback range',
594 export_frame_step
: IntProperty(
595 name
='Sampling Rate',
596 description
='How often to evaluate animated values (in frames)',
602 export_force_sampling
: BoolProperty(
603 name
='Always Sample Animations',
604 description
='Apply sampling to all animations',
608 export_pointer_animation
: BoolProperty(
609 name
='Export Animation Pointer (Experimental)',
610 description
='Export material, Light & Camera animation as Animation Pointer',
614 export_animation_mode
: EnumProperty(
615 name
='Animation mode',
616 items
=(('ACTIONS', 'Actions',
617 'Export actions (actives and on NLA tracks) as separate animations'),
618 ('ACTIVE_ACTIONS', 'Active actions merged',
619 'All the currently assigned actions become one glTF animation'),
620 ('BROADCAST', 'Broadcast actions',
621 'Broadcast all compatible actions to all objects. '
622 'Animated objects will get all actions compatible with them, '
623 'others will get no animation at all'),
624 ('NLA_TRACKS', 'NLA Tracks',
625 'Export individual NLA Tracks as separate animation'),
627 'Export baked scene as a single animation')
629 description
='Export Animation mode',
633 export_nla_strips_merged_animation_name
: StringProperty(
634 name
='Merged Animation Name',
636 "Name of single glTF animation to be exported"
641 export_def_bones
: BoolProperty(
642 name
='Export Deformation Bones Only',
643 description
='Export Deformation bones only',
647 export_hierarchy_flatten_bones
: BoolProperty(
648 name
='Flatten Bone Hierarchy',
649 description
='Flatten Bone Hierarchy. Useful in case of non decomposable transformation matrix',
653 export_hierarchy_flatten_objs
: BoolProperty(
654 name
='Flatten Object Hierarchy',
655 description
='Flatten Object Hierarchy. Useful in case of non decomposable transformation matrix',
659 export_armature_object_remove
: BoolProperty(
660 name
='Remove Armature Object',
662 'Remove Armature object if possible. '
663 'If Armature has multiple root bones, object will not be removed'
668 export_leaf_bone
: BoolProperty(
669 name
='Add Leaf Bones',
671 'Append a final bone to the end of each chain to specify last bone length '
672 '(use this when you intend to edit the armature from exported data)'
677 export_optimize_animation_size
: BoolProperty(
678 name
='Optimize Animation Size',
680 "Reduce exported file size by removing duplicate keyframes"
685 export_optimize_animation_keep_anim_armature
: BoolProperty(
686 name
='Force keeping channels for bones',
688 "If all keyframes are identical in a rig, "
689 "force keeping the minimal animation. "
690 "When off, all possible channels for "
691 "the bones will be exported, even if empty "
692 "(minimal animation, 2 keyframes)"
697 export_optimize_animation_keep_anim_object
: BoolProperty(
698 name
='Force keeping channel for objects',
700 "If all keyframes are identical for object transformations, "
701 "force keeping the minimal animation"
706 export_optimize_armature_disable_viewport
: BoolProperty(
707 name
='Disable viewport if possible',
709 "When exporting armature, disable viewport for other objects, "
710 "for performance. Drivers on shape keys for skined meshes prevent this optimization for now"
715 export_negative_frame
: EnumProperty(
716 name
='Negative Frames',
717 items
=(('SLIDE', 'Slide',
718 'Slide animation to start at frame 0'),
720 'Keep only frames above frame 0'),
722 description
='Negative Frames are slid or cropped',
726 export_anim_slide_to_zero
: BoolProperty(
727 name
='Set all glTF Animation starting at 0',
729 "Set all glTF animation starting at 0.0s. "
730 "Can be useful for looping animations"
735 export_bake_animation
: BoolProperty(
736 name
='Bake All Objects Animations',
738 "Force exporting animation on every object. "
739 "Can be useful when using constraints or driver. "
740 "Also useful when exporting only selection"
745 export_anim_single_armature
: BoolProperty(
746 name
='Export all Armature Actions',
748 "Export all actions, bound to a single armature. "
749 "WARNING: Option does not support exports including multiple armatures"
754 export_reset_pose_bones
: BoolProperty(
755 name
='Reset pose bones between actions',
757 "Reset pose bones between each action exported. "
758 "This is needed when some bones are not keyed on some animations"
763 export_current_frame
: BoolProperty(
764 name
='Use Current Frame as Object Rest Transformations',
766 'Export the scene in the current animation frame. '
767 'When off, frame 0 is used as rest transformations for objects'
772 export_rest_position_armature
: BoolProperty(
773 name
='Use Rest Position Armature',
775 "Export armatures using rest position as joints' rest pose. "
776 "When off, current frame pose is used as rest pose"
781 export_anim_scene_split_object
: BoolProperty(
782 name
='Split Animation by Object',
784 "Export Scene as seen in Viewport, "
785 "But split animation by Object"
790 export_skins
: BoolProperty(
792 description
='Export skinning (armature) data',
796 export_influence_nb
: IntProperty(
797 name
='Bone Influences',
798 description
='Choose how many Bone influences to export',
803 export_all_influences
: BoolProperty(
804 name
='Include All Bone Influences',
805 description
='Allow export of all joint vertex influences. Models may appear incorrectly in many viewers',
809 export_morph
: BoolProperty(
811 description
='Export shape keys (morph targets)',
815 export_morph_normal
: BoolProperty(
816 name
='Shape Key Normals',
817 description
='Export vertex normals with shape keys (morph targets)',
821 export_morph_tangent
: BoolProperty(
822 name
='Shape Key Tangents',
823 description
='Export vertex tangents with shape keys (morph targets)',
827 export_morph_animation
: BoolProperty(
828 name
='Shape Key Animations',
829 description
='Export shape keys animations (morph targets)',
833 export_morph_reset_sk_data
: BoolProperty(
834 name
='Reset shape keys between actions',
836 "Reset shape keys between each action exported. "
837 "This is needed when some SK channels are not keyed on some animations"
842 export_lights
: BoolProperty(
843 name
='Punctual Lights',
844 description
='Export directional, point, and spot lights. '
845 'Uses "KHR_lights_punctual" glTF extension',
849 export_try_sparse_sk
: BoolProperty(
850 name
='Use Sparse Accessor if better',
851 description
='Try using Sparse Accessor if it saves space',
855 export_try_omit_sparse_sk
: BoolProperty(
856 name
='Omitting Sparse Accessor if data is empty',
857 description
='Omitting Sparse Accessor if data is empty',
861 export_gpu_instances
: BoolProperty(
862 name
='GPU Instances',
863 description
='Export using EXT_mesh_gpu_instancing. '
864 'Limited to children of a given Empty. '
865 'Multiple materials might be omitted',
869 export_action_filter
: BoolProperty(
870 name
='Filter Actions',
871 description
='Filter Actions to be exported',
873 update
=on_export_action_filter_changed
,
876 export_convert_animation_pointer
: BoolProperty(
877 name
='Convert TRS/weights to Animation Pointer',
878 description
='Export TRS and weights as Animation Pointer. '
879 'Using KHR_animation_pointer extension',
883 # This parameter is only here for backward compatibility, as this option is removed in 3.6
884 # This option does nothing, and is not displayed in UI
885 # What you are looking for is probably "export_animation_mode"
886 export_nla_strips
: BoolProperty(
887 name
='Group by NLA Track',
889 "When on, multiple actions become part of the same glTF animation if "
890 "they're pushed onto NLA tracks with the same name. "
891 "When off, all the currently assigned actions become one glTF animation"
896 # Keep for back compatibility, but no more used
897 export_original_specular
: BoolProperty(
898 name
='Export original PBR Specular',
900 'Export original glTF PBR Specular, instead of Blender Principled Shader Specular'
905 will_save_settings
: BoolProperty(
906 name
='Remember Export Settings',
907 description
='Store glTF export settings in the Blender project',
910 export_hierarchy_full_collections
: BoolProperty(
911 name
='Full Collection Hierarchy',
912 description
='Export full hierarchy, including intermediate collections',
916 export_extra_animations
: BoolProperty(
917 name
='Prepare extra animations',
919 'Export additional animations'
920 'This feature is not standard and needs an external extension to be included in the glTF file'
925 # Custom scene property for saving settings
926 scene_key
= "glTF2ExportSettings"
930 def check(self
, _context
):
931 # Ensure file extension matches format
932 old_filepath
= self
.filepath
933 self
.filepath
= ensure_filepath_matches_export_format(
937 return self
.filepath
!= old_filepath
939 def invoke(self
, context
, event
):
940 settings
= context
.scene
.get(self
.scene_key
)
941 self
.will_save_settings
= False
944 for (k
, v
) in settings
.items():
946 self
.will_save_settings
= True
948 # Update filter if user saved settings
949 if hasattr(self
, 'export_format'):
950 self
.filter_glob
= '*.glb' if self
.export_format
== 'GLB' else '*.gltf'
952 except (AttributeError, TypeError):
953 self
.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
954 del context
.scene
[self
.scene_key
]
957 preferences
= bpy
.context
.preferences
958 for addon_name
in preferences
.addons
.keys():
960 if hasattr(sys
.modules
[addon_name
], 'glTF2ExportUserExtension') or hasattr(sys
.modules
[addon_name
], 'glTF2ExportUserExtensions'):
961 exporter_extension_panel_unregister_functors
.append(sys
.modules
[addon_name
].register_panel())
965 self
.has_active_exporter_extensions
= len(exporter_extension_panel_unregister_functors
) > 0
966 return ExportHelper
.invoke(self
, context
, event
)
968 def save_settings(self
, context
):
969 # find all props to save
971 # options that don't start with 'export_'
975 'use_active_collection_with_nested',
976 'use_active_collection',
982 all_props
= self
.properties
984 x
: getattr(self
, x
) for x
in dir(all_props
)
985 if (x
.startswith("export_") or x
in exceptional
) and all_props
.get(x
) is not None
987 context
.scene
[self
.scene_key
] = export_props
989 def execute(self
, context
):
993 from .io
.com
.gltf2_io_debug
import Log
994 from .blender
.exp
import gltf2_blender_export
995 from .io
.com
.gltf2_io_path
import path_to_uri
997 if self
.will_save_settings
:
998 self
.save_settings(context
)
1000 self
.check(context
) # ensure filepath has the right extension
1002 # All custom export settings are stored in this container.
1003 export_settings
= {}
1005 export_settings
['loglevel'] = logging
.INFO
1007 export_settings
['exported_images'] = {}
1008 export_settings
['exported_texture_nodes'] = []
1009 export_settings
['additional_texture_export'] = []
1010 export_settings
['additional_texture_export_current_idx'] = 0
1012 export_settings
['timestamp'] = datetime
.datetime
.now()
1013 export_settings
['gltf_export_id'] = self
.gltf_export_id
1014 export_settings
['gltf_filepath'] = self
.filepath
1015 export_settings
['gltf_filedirectory'] = os
.path
.dirname(export_settings
['gltf_filepath']) + '/'
1016 export_settings
['gltf_texturedirectory'] = os
.path
.join(
1017 export_settings
['gltf_filedirectory'],
1018 self
.export_texture_dir
,
1020 export_settings
['gltf_keep_original_textures'] = self
.export_keep_originals
1022 export_settings
['gltf_format'] = self
.export_format
1023 export_settings
['gltf_image_format'] = self
.export_image_format
1024 export_settings
['gltf_add_webp'] = self
.export_image_add_webp
1025 export_settings
['gltf_webp_fallback'] = self
.export_image_webp_fallback
1026 export_settings
['gltf_image_quality'] = self
.export_image_quality
1027 export_settings
['gltf_copyright'] = self
.export_copyright
1028 export_settings
['gltf_texcoords'] = self
.export_texcoords
1029 export_settings
['gltf_normals'] = self
.export_normals
1030 export_settings
['gltf_tangents'] = self
.export_tangents
and self
.export_normals
1031 export_settings
['gltf_loose_edges'] = self
.use_mesh_edges
1032 export_settings
['gltf_loose_points'] = self
.use_mesh_vertices
1034 if is_draco_available():
1035 export_settings
['gltf_draco_mesh_compression'] = self
.export_draco_mesh_compression_enable
1036 export_settings
['gltf_draco_mesh_compression_level'] = self
.export_draco_mesh_compression_level
1037 export_settings
['gltf_draco_position_quantization'] = self
.export_draco_position_quantization
1038 export_settings
['gltf_draco_normal_quantization'] = self
.export_draco_normal_quantization
1039 export_settings
['gltf_draco_texcoord_quantization'] = self
.export_draco_texcoord_quantization
1040 export_settings
['gltf_draco_color_quantization'] = self
.export_draco_color_quantization
1041 export_settings
['gltf_draco_generic_quantization'] = self
.export_draco_generic_quantization
1043 export_settings
['gltf_draco_mesh_compression'] = False
1045 export_settings
['gltf_gn_mesh'] = self
.export_gn_mesh
1047 export_settings
['gltf_materials'] = self
.export_materials
1048 export_settings
['gltf_attributes'] = self
.export_attributes
1049 export_settings
['gltf_cameras'] = self
.export_cameras
1051 export_settings
['gltf_unused_textures'] = self
.export_unused_textures
1052 export_settings
['gltf_unused_images'] = self
.export_unused_images
1054 export_settings
['gltf_visible'] = self
.use_visible
1055 export_settings
['gltf_renderable'] = self
.use_renderable
1057 export_settings
['gltf_active_collection'] = self
.use_active_collection
1058 if self
.use_active_collection
:
1059 export_settings
['gltf_active_collection_with_nested'] = self
.use_active_collection_with_nested
1061 export_settings
['gltf_active_collection_with_nested'] = False
1062 export_settings
['gltf_active_scene'] = self
.use_active_scene
1063 export_settings
['gltf_collection'] = self
.collection
1065 export_settings
['gltf_selected'] = self
.use_selection
1066 export_settings
['gltf_layers'] = True # self.export_layers
1067 export_settings
['gltf_extras'] = self
.export_extras
1068 export_settings
['gltf_yup'] = self
.export_yup
1069 export_settings
['gltf_apply'] = self
.export_apply
1070 export_settings
['gltf_shared_accessors'] = self
.export_shared_accessors
1071 export_settings
['gltf_current_frame'] = self
.export_current_frame
1072 export_settings
['gltf_animations'] = self
.export_animations
1073 export_settings
['gltf_def_bones'] = self
.export_def_bones
1074 export_settings
['gltf_flatten_bones_hierarchy'] = self
.export_hierarchy_flatten_bones
1075 export_settings
['gltf_flatten_obj_hierarchy'] = self
.export_hierarchy_flatten_objs
1076 export_settings
['gltf_armature_object_remove'] = self
.export_armature_object_remove
1077 export_settings
['gltf_leaf_bone'] = self
.export_leaf_bone
1078 if self
.export_animations
:
1079 export_settings
['gltf_frame_range'] = self
.export_frame_range
1080 export_settings
['gltf_force_sampling'] = self
.export_force_sampling
1081 if not self
.export_force_sampling
:
1082 export_settings
['gltf_def_bones'] = False
1083 export_settings
['gltf_bake_animation'] = False
1084 export_settings
['gltf_animation_mode'] = self
.export_animation_mode
1085 if export_settings
['gltf_animation_mode'] == "NLA_TRACKS":
1086 export_settings
['gltf_force_sampling'] = True
1087 if export_settings
['gltf_animation_mode'] == "SCENE":
1088 export_settings
['gltf_anim_scene_split_object'] = self
.export_anim_scene_split_object
1090 export_settings
['gltf_anim_scene_split_object'] = False
1092 if export_settings
['gltf_animation_mode'] in ['NLA_TRACKS', 'SCENE']:
1093 export_settings
['gltf_export_anim_pointer'] = self
.export_pointer_animation
1094 if self
.export_pointer_animation
:
1095 export_settings
['gltf_trs_w_animation_pointer'] = self
.export_convert_animation_pointer
1097 export_settings
['gltf_trs_w_animation_pointer'] = False
1099 export_settings
['gltf_trs_w_animation_pointer'] = False
1100 export_settings
['gltf_export_anim_pointer'] = False
1102 export_settings
['gltf_nla_strips_merged_animation_name'] = self
.export_nla_strips_merged_animation_name
1103 export_settings
['gltf_optimize_animation'] = self
.export_optimize_animation_size
1104 export_settings
['gltf_optimize_animation_keep_armature'] = self
.export_optimize_animation_keep_anim_armature
1105 export_settings
['gltf_optimize_animation_keep_object'] = self
.export_optimize_animation_keep_anim_object
1106 export_settings
['gltf_optimize_armature_disable_viewport'] = self
.export_optimize_armature_disable_viewport
1107 export_settings
['gltf_export_anim_single_armature'] = self
.export_anim_single_armature
1108 export_settings
['gltf_export_reset_pose_bones'] = self
.export_reset_pose_bones
1109 export_settings
['gltf_export_reset_sk_data'] = self
.export_morph_reset_sk_data
1110 export_settings
['gltf_bake_animation'] = self
.export_bake_animation
1111 export_settings
['gltf_negative_frames'] = self
.export_negative_frame
1112 export_settings
['gltf_anim_slide_to_zero'] = self
.export_anim_slide_to_zero
1113 export_settings
['gltf_export_extra_animations'] = self
.export_extra_animations
1115 export_settings
['gltf_frame_range'] = False
1116 export_settings
['gltf_force_sampling'] = False
1117 export_settings
['gltf_bake_animation'] = False
1118 export_settings
['gltf_optimize_animation'] = False
1119 export_settings
['gltf_optimize_animation_keep_armature'] = False
1120 export_settings
['gltf_optimize_animation_keep_object'] = False
1121 export_settings
['gltf_optimize_armature_disable_viewport'] = False
1122 export_settings
['gltf_export_anim_single_armature'] = False
1123 export_settings
['gltf_export_reset_pose_bones'] = False
1124 export_settings
['gltf_export_reset_sk_data'] = False
1125 export_settings
['gltf_export_extra_animations'] = False
1126 export_settings
['gltf_skins'] = self
.export_skins
1127 if self
.export_skins
:
1128 export_settings
['gltf_all_vertex_influences'] = self
.export_all_influences
1129 export_settings
['gltf_vertex_influences_nb'] = self
.export_influence_nb
1131 export_settings
['gltf_all_vertex_influences'] = False
1132 export_settings
['gltf_def_bones'] = False
1133 export_settings
['gltf_rest_position_armature'] = self
.export_rest_position_armature
1134 export_settings
['gltf_frame_step'] = self
.export_frame_step
1136 export_settings
['gltf_morph'] = self
.export_morph
1137 if self
.export_morph
:
1138 export_settings
['gltf_morph_normal'] = self
.export_morph_normal
1139 export_settings
['gltf_morph_tangent'] = self
.export_morph_tangent
1140 export_settings
['gltf_morph_anim'] = self
.export_morph_animation
1142 export_settings
['gltf_morph_normal'] = False
1143 export_settings
['gltf_morph_tangent'] = False
1144 export_settings
['gltf_morph_anim'] = False
1146 export_settings
['gltf_lights'] = self
.export_lights
1147 export_settings
['gltf_lighting_mode'] = self
.export_import_convert_lighting_mode
1149 export_settings
['gltf_gpu_instances'] = self
.export_gpu_instances
1151 export_settings
['gltf_try_sparse_sk'] = self
.export_try_sparse_sk
1152 export_settings
['gltf_try_omit_sparse_sk'] = self
.export_try_omit_sparse_sk
1153 if not self
.export_try_sparse_sk
:
1154 export_settings
['gltf_try_omit_sparse_sk'] = False
1156 export_settings
['gltf_hierarchy_full_collections'] = self
.export_hierarchy_full_collections
1159 export_settings
['gltf_use_gltfpack'] = self
.export_use_gltfpack
1160 if self
.export_use_gltfpack
:
1161 export_settings
['gltf_gltfpack_tc'] = self
.export_gltfpack_tc
1162 export_settings
['gltf_gltfpack_tq'] = self
.export_gltfpack_tq
1164 export_settings
['gltf_gltfpack_si'] = self
.export_gltfpack_si
1165 export_settings
['gltf_gltfpack_sa'] = self
.export_gltfpack_sa
1166 export_settings
['gltf_gltfpack_slb'] = self
.export_gltfpack_slb
1168 export_settings
['gltf_gltfpack_vp'] = self
.export_gltfpack_vp
1169 export_settings
['gltf_gltfpack_vt'] = self
.export_gltfpack_vt
1170 export_settings
['gltf_gltfpack_vn'] = self
.export_gltfpack_vn
1171 export_settings
['gltf_gltfpack_vc'] = self
.export_gltfpack_vc
1173 export_settings
['gltf_gltfpack_vpi'] = self
.export_gltfpack_vpi
1175 export_settings
['gltf_gltfpack_noq'] = self
.export_gltfpack_noq
1177 export_settings
['gltf_binary'] = bytearray()
1178 export_settings
['gltf_binaryfilename'] = (
1179 path_to_uri(os
.path
.splitext(os
.path
.basename(self
.filepath
))[0] + '.bin')
1182 user_extensions
= []
1183 pre_export_callbacks
= []
1184 post_export_callbacks
= []
1187 preferences
= bpy
.context
.preferences
1188 for addon_name
in preferences
.addons
.keys():
1190 module
= sys
.modules
[addon_name
]
1193 if hasattr(module
, 'glTF2ExportUserExtension'):
1194 extension_ctor
= module
.glTF2ExportUserExtension
1195 user_extensions
.append(extension_ctor())
1196 if hasattr(module
, 'glTF2ExportUserExtensions'):
1197 extension_ctors
= module
.glTF2ExportUserExtensions
1198 for extension_ctor
in extension_ctors
:
1199 user_extensions
.append(extension_ctor())
1200 if hasattr(module
, 'glTF2_pre_export_callback'):
1201 pre_export_callbacks
.append(module
.glTF2_pre_export_callback
)
1202 if hasattr(module
, 'glTF2_post_export_callback'):
1203 post_export_callbacks
.append(module
.glTF2_post_export_callback
)
1204 export_settings
['gltf_user_extensions'] = user_extensions
1205 export_settings
['pre_export_callbacks'] = pre_export_callbacks
1206 export_settings
['post_export_callbacks'] = post_export_callbacks
1209 # Initialize logging for export
1210 export_settings
['log'] = Log(export_settings
['loglevel'])
1213 profile
= bpy
.app
.debug_value
== 102
1215 import cProfile
, pstats
, io
1216 from pstats
import SortKey
1217 pr
= cProfile
.Profile()
1219 res
= gltf2_blender_export
.save(context
, export_settings
)
1222 sortby
= SortKey
.TIME
1223 ps
= pstats
.Stats(pr
, stream
=s
).sort_stats(sortby
)
1227 res
= gltf2_blender_export
.save(context
, export_settings
)
1229 # Display popup log, if any
1230 for message_type
, message
in export_settings
['log'].messages():
1231 self
.report({message_type}
, message
)
1233 export_settings
['log'].flush()
1237 def draw(self
, context
):
1239 layout
= self
.layout
1240 layout
.use_property_split
= True
1241 layout
.use_property_decorate
= False # No animation.
1243 # Are we inside the File browser
1244 is_file_browser
= context
.space_data
.type == 'FILE_BROWSER'
1246 export_main(layout
, operator
, is_file_browser
)
1247 export_panel_include(layout
, operator
, is_file_browser
)
1248 export_panel_transform(layout
, operator
)
1249 export_panel_data(layout
, operator
)
1250 export_panel_animation(layout
, operator
)
1252 # If gltfpack is not setup in plugin preferences -> don't show any gltfpack relevant options in export dialog
1253 gltfpack_path
= context
.preferences
.addons
['io_scene_gltf2'].preferences
.gltfpack_path_ui
.strip()
1254 if gltfpack_path
!= '':
1255 export_panel_gltfpack(layout
, operator
)
1257 def export_main(layout
, operator
, is_file_browser
):
1258 layout
.prop(operator
, 'export_format')
1259 if operator
.export_format
== 'GLTF_SEPARATE':
1260 layout
.prop(operator
, 'export_keep_originals')
1261 if operator
.export_keep_originals
is False:
1262 layout
.prop(operator
, 'export_texture_dir', icon
='FILE_FOLDER')
1263 if operator
.export_format
== 'GLTF_EMBEDDED':
1264 layout
.label(text
="This is the least efficient of the available forms, and should only be used when required.", icon
='ERROR')
1266 layout
.prop(operator
, 'export_copyright')
1268 layout
.prop(operator
, 'will_save_settings')
1271 def export_panel_include(layout
, operator
, is_file_browser
):
1272 header
, body
= layout
.panel("GLTF_export_include", default_closed
=True)
1273 header
.label(text
="Include")
1276 col
= body
.column(heading
= "Limit to", align
= True)
1277 col
.prop(operator
, 'use_selection')
1278 col
.prop(operator
, 'use_visible')
1279 col
.prop(operator
, 'use_renderable')
1280 col
.prop(operator
, 'use_active_collection')
1281 if operator
.use_active_collection
:
1282 col
.prop(operator
, 'use_active_collection_with_nested')
1283 col
.prop(operator
, 'use_active_scene')
1285 col
= body
.column(heading
= "Data", align
= True)
1286 col
.prop(operator
, 'export_extras')
1287 col
.prop(operator
, 'export_cameras')
1288 col
.prop(operator
, 'export_lights')
1291 def export_panel_transform(layout
, operator
):
1292 header
, body
= layout
.panel("GLTF_export_transform", default_closed
=True)
1293 header
.label(text
="Transform")
1295 body
.prop(operator
, 'export_yup')
1298 def export_panel_data(layout
, operator
):
1299 header
, body
= layout
.panel("GLTF_export_data", default_closed
=True)
1300 header
.label(text
="Data")
1302 export_panel_data_scene_graph(body
, operator
)
1303 export_panel_data_mesh(body
, operator
)
1304 export_panel_data_material(body
, operator
)
1305 export_panel_data_shapekeys(body
, operator
)
1306 export_panel_data_armature(body
, operator
)
1307 export_panel_data_skinning(body
, operator
)
1308 export_panel_data_lighting(body
, operator
)
1310 if is_draco_available():
1311 export_panel_data_compression(body
, operator
)
1314 def export_panel_data_scene_graph(layout
, operator
):
1315 header
, body
= layout
.panel("GLTF_export_data_scene_graph", default_closed
=True)
1316 header
.label(text
="Scene Graph")
1318 body
.prop(operator
, 'export_gn_mesh')
1319 body
.prop(operator
, 'export_gpu_instances')
1320 body
.prop(operator
, 'export_hierarchy_flatten_objs')
1321 body
.prop(operator
, 'export_hierarchy_full_collections')
1324 def export_panel_data_mesh(layout
, operator
):
1325 header
, body
= layout
.panel("GLTF_export_data_mesh", default_closed
=True)
1326 header
.label(text
="Mesh")
1328 body
.prop(operator
, 'export_apply')
1329 body
.prop(operator
, 'export_texcoords')
1330 body
.prop(operator
, 'export_normals')
1332 col
.active
= operator
.export_normals
1333 col
.prop(operator
, 'export_tangents')
1334 body
.prop(operator
, 'export_attributes')
1337 col
.prop(operator
, 'use_mesh_edges')
1338 col
.prop(operator
, 'use_mesh_vertices')
1341 col
.prop(operator
, 'export_shared_accessors')
1344 def export_panel_data_material(layout
, operator
):
1345 header
, body
= layout
.panel("GLTF_export_data_material", default_closed
=True)
1346 header
.label(text
="Material")
1348 body
.prop(operator
, 'export_materials')
1350 col
.active
= operator
.export_materials
== "EXPORT"
1351 col
.prop(operator
, 'export_image_format')
1352 if operator
.export_image_format
in ["AUTO", "JPEG", "WEBP"]:
1353 col
.prop(operator
, 'export_image_quality')
1355 col
.active
= operator
.export_image_format
!= "WEBP"
1356 col
.prop(operator
, "export_image_add_webp")
1358 col
.active
= operator
.export_image_format
!= "WEBP"
1359 col
.prop(operator
, "export_image_webp_fallback")
1361 header
, sub_body
= body
.panel("GLTF_export_data_material_unused", default_closed
=True)
1362 header
.label(text
="Unused Textures & Images")
1364 row
= sub_body
.row()
1365 row
.prop(operator
, 'export_unused_images')
1366 row
= sub_body
.row()
1367 row
.prop(operator
, 'export_unused_textures')
1370 def export_panel_data_shapekeys(layout
, operator
):
1371 header
, body
= layout
.panel("GLTF_export_data_shapekeys", default_closed
=True)
1372 header
.use_property_split
= False
1373 header
.prop(operator
, "export_morph", text
="")
1374 header
.label(text
="Shape Keys")
1376 body
.active
= operator
.export_morph
1378 body
.prop(operator
, 'export_morph_normal')
1380 col
.active
= operator
.export_morph_normal
1381 col
.prop(operator
, 'export_morph_tangent')
1383 # Data-Shape Keys-Optimize
1384 header
, sub_body
= body
.panel("GLTF_export_data_shapekeys_optimize", default_closed
=True)
1385 header
.label(text
="Optimize Shape Keys")
1387 row
= sub_body
.row()
1388 row
.prop(operator
, 'export_try_sparse_sk')
1390 row
= sub_body
.row()
1391 row
.active
= operator
.export_try_sparse_sk
1392 row
.prop(operator
, 'export_try_omit_sparse_sk')
1395 def export_panel_data_armature(layout
, operator
):
1396 header
, body
= layout
.panel("GLTF_export_data_armature", default_closed
=True)
1397 header
.label(text
="Armature")
1399 body
.active
= operator
.export_skins
1401 body
.prop(operator
, 'export_rest_position_armature')
1404 row
.active
= operator
.export_force_sampling
1405 row
.prop(operator
, 'export_def_bones')
1406 if operator
.export_force_sampling
is False and operator
.export_def_bones
is True:
1407 body
.label(text
="Export only deformation bones is not possible when not sampling animation")
1409 row
.prop(operator
, 'export_armature_object_remove')
1411 row
.prop(operator
, 'export_hierarchy_flatten_bones')
1414 def export_panel_data_skinning(layout
, operator
):
1415 header
, body
= layout
.panel("GLTF_export_data_skinning", default_closed
=True)
1416 header
.use_property_split
= False
1417 header
.prop(operator
, "export_skins", text
="")
1418 header
.label(text
="Skinning")
1420 body
.active
= operator
.export_skins
1423 row
.prop(operator
, 'export_influence_nb')
1424 row
.active
= not operator
.export_all_influences
1425 body
.prop(operator
, 'export_all_influences')
1428 def export_panel_data_lighting(layout
, operator
):
1429 header
, body
= layout
.panel("GLTF_export_data_lighting", default_closed
=True)
1430 header
.label(text
="Lighting")
1432 body
.prop(operator
, 'export_import_convert_lighting_mode')
1435 def export_panel_data_compression(layout
, operator
):
1436 header
, body
= layout
.panel("GLTF_export_data_compression", default_closed
=True)
1437 header
.use_property_split
= False
1438 header
.prop(operator
, "export_draco_mesh_compression_enable", text
="")
1439 header
.label(text
="Compression")
1441 body
.active
= operator
.export_draco_mesh_compression_enable
1443 body
.prop(operator
, 'export_draco_mesh_compression_level')
1445 col
= body
.column(align
=True)
1446 col
.prop(operator
, 'export_draco_position_quantization', text
="Quantize Position")
1447 col
.prop(operator
, 'export_draco_normal_quantization', text
="Normal")
1448 col
.prop(operator
, 'export_draco_texcoord_quantization', text
="Tex Coord")
1449 col
.prop(operator
, 'export_draco_color_quantization', text
="Color")
1450 col
.prop(operator
, 'export_draco_generic_quantization', text
="Generic")
1453 def export_panel_animation(layout
, operator
):
1454 header
, body
= layout
.panel("GLTF_export_animation", default_closed
=True)
1455 header
.use_property_split
= False
1456 header
.prop(operator
, "export_animations", text
="")
1457 header
.label(text
="Animation")
1459 body
.active
= operator
.export_animations
1461 body
.prop(operator
, 'export_animation_mode')
1462 if operator
.export_animation_mode
== "ACTIVE_ACTIONS":
1463 layout
.prop(operator
, 'export_nla_strips_merged_animation_name')
1466 row
.active
= operator
.export_force_sampling
and operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS', 'BROACAST']
1467 row
.prop(operator
, 'export_bake_animation')
1468 if operator
.export_animation_mode
== "SCENE":
1469 body
.prop(operator
, 'export_anim_scene_split_object')
1472 if operator
.export_animation_mode
in ["NLA_TRACKS", "SCENE"]:
1473 export_panel_animation_notes(body
, operator
)
1474 export_panel_animation_ranges(body
, operator
)
1475 export_panel_animation_armature(body
, operator
)
1476 export_panel_animation_shapekeys(body
, operator
)
1477 export_panel_animation_sampling(body
, operator
)
1478 export_panel_animation_pointer(body
, operator
)
1479 export_panel_animation_optimize(body
, operator
)
1480 if operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS']:
1481 export_panel_animation_extra(body
, operator
)
1483 from .blender
.com
.gltf2_blender_ui
import export_panel_animation_action_filter
1484 export_panel_animation_action_filter(body
, operator
)
1487 def export_panel_animation_notes(layout
, operator
):
1488 header
, body
= layout
.panel("GLTF_export_animation_notes", default_closed
=True)
1489 header
.label(text
="Notes")
1491 if operator
.export_animation_mode
== "SCENE":
1492 body
.label(text
="Scene mode uses full bake mode:")
1493 body
.label(text
="- sampling is active")
1494 body
.label(text
="- baking all objects is active")
1495 body
.label(text
="- Using scene frame range")
1496 elif operator
.export_animation_mode
== "NLA_TRACKS":
1497 body
.label(text
="Track mode uses full bake mode:")
1498 body
.label(text
="- sampling is active")
1499 body
.label(text
="- baking all objects is active")
1502 def export_panel_animation_ranges(layout
, operator
):
1503 header
, body
= layout
.panel("GLTF_export_animation_ranges", default_closed
=True)
1504 header
.label(text
="Rest & Ranges")
1506 body
.active
= operator
.export_animations
1508 body
.prop(operator
, 'export_current_frame')
1510 row
.active
= operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS', 'BROADCAST', 'NLA_TRACKS']
1511 row
.prop(operator
, 'export_frame_range')
1512 body
.prop(operator
, 'export_anim_slide_to_zero')
1514 row
.active
= operator
.export_animation_mode
in ['ACTIONS', 'ACTIVE_ACTIONS', 'BROADCAST', 'NLA_TRACKS']
1515 body
.prop(operator
, 'export_negative_frame')
1518 def export_panel_animation_armature(layout
, operator
):
1519 header
, body
= layout
.panel("GLTF_export_animation_armature", default_closed
=True)
1520 header
.label(text
="Armature")
1522 body
.active
= operator
.export_animations
1524 body
.prop(operator
, 'export_anim_single_armature')
1525 body
.prop(operator
, 'export_reset_pose_bones')
1528 def export_panel_animation_shapekeys(layout
, operator
):
1529 header
, body
= layout
.panel("GLTF_export_animation_shapekeys", default_closed
=True)
1530 header
.use_property_split
= False
1531 header
.prop(operator
, "export_morph_animation", text
="")
1532 header
.label(text
="Shape Keys Animation")
1534 body
.active
= operator
.export_animations
1536 body
.prop(operator
, 'export_morph_reset_sk_data')
1539 def export_panel_animation_sampling(layout
, operator
):
1540 header
, body
= layout
.panel("GLTF_export_animation_sampling", default_closed
=True)
1541 header
.use_property_split
= False
1542 header
.prop(operator
, "export_force_sampling", text
="")
1543 header
.label(text
="Sampling Animations")
1545 body
.active
= operator
.export_animations
1547 body
.prop(operator
, 'export_frame_step')
1549 def export_panel_animation_pointer(layout
, operator
):
1550 header
, body
= layout
.panel("GLTF_export_animation_pointer", default_closed
=True)
1551 header
.use_property_split
= False
1552 header
.active
= operator
.export_animations
and operator
.export_animation_mode
in ['NLA_TRACKS', 'SCENE']
1553 header
.prop(operator
, "export_pointer_animation", text
="")
1554 header
.label(text
="Animation Pointer (Experimental)")
1559 row
.active
= operator
.export_pointer_animation
1560 row
.prop(operator
, 'export_convert_animation_pointer')
1562 def export_panel_animation_optimize(layout
, operator
):
1563 header
, body
= layout
.panel("GLTF_export_animation_optimize", default_closed
=True)
1564 header
.label(text
="Optimize Animations")
1566 body
.active
= operator
.export_animations
1568 body
.prop(operator
, 'export_optimize_animation_size')
1571 row
.prop(operator
, 'export_optimize_animation_keep_anim_armature')
1574 row
.prop(operator
, 'export_optimize_animation_keep_anim_object')
1577 row
.prop(operator
, 'export_optimize_armature_disable_viewport')
1580 def export_panel_animation_extra(layout
, operator
):
1581 header
, body
= layout
.panel("GLTF_export_animation_extra", default_closed
=True)
1582 header
.label(text
="Extra Animations")
1584 body
.active
= operator
.export_animations
1586 body
.prop(operator
, 'export_extra_animations')
1589 def export_panel_gltfpack(layout
, operator
):
1590 header
, body
= layout
.panel("GLTF_export_gltfpack", default_closed
=True)
1591 header
.label(text
="gltfpack")
1593 col
= body
.column(heading
= "gltfpack", align
= True)
1594 col
.prop(operator
, 'export_use_gltfpack')
1596 col
= body
.column(heading
= "Textures", align
= True)
1597 col
.prop(operator
, 'export_gltfpack_tc')
1598 col
.prop(operator
, 'export_gltfpack_tq')
1599 col
= body
.column(heading
= "Simplification", align
= True)
1600 col
.prop(operator
, 'export_gltfpack_si')
1601 col
.prop(operator
, 'export_gltfpack_sa')
1602 col
.prop(operator
, 'export_gltfpack_slb')
1603 col
= body
.column(heading
= "Vertices", align
= True)
1604 col
.prop(operator
, 'export_gltfpack_vp')
1605 col
.prop(operator
, 'export_gltfpack_vt')
1606 col
.prop(operator
, 'export_gltfpack_vn')
1607 col
.prop(operator
, 'export_gltfpack_vc')
1608 col
= body
.column(heading
= "Vertex positions", align
= True)
1609 col
.prop(operator
, 'export_gltfpack_vpi')
1610 #col = body.column(heading = "Animations", align = True)
1611 #col = body.column(heading = "Scene", align = True)
1612 col
= body
.column(heading
= "Miscellaneous", align
= True)
1613 col
.prop(operator
, 'export_gltfpack_noq')
1616 class ExportGLTF2(bpy
.types
.Operator
, ExportGLTF2_Base
, ExportHelper
):
1617 """Export scene as glTF 2.0 file"""
1618 bl_idname
= 'export_scene.gltf'
1619 bl_label
= 'Export glTF 2.0'
1623 filter_glob
: StringProperty(default
='*.glb', options
={'HIDDEN'})
1626 def menu_func_export(self
, context
):
1627 self
.layout
.operator(ExportGLTF2
.bl_idname
, text
='glTF 2.0 (.glb/.gltf)')
1630 class ImportGLTF2(Operator
, ConvertGLTF2_Base
, ImportHelper
):
1631 """Load a glTF 2.0 file"""
1632 bl_idname
= 'import_scene.gltf'
1633 bl_label
= 'Import glTF 2.0'
1634 bl_options
= {'REGISTER', 'UNDO'}
1636 filter_glob
: StringProperty(default
="*.glb;*.gltf", options
={'HIDDEN'})
1638 files
: CollectionProperty(
1640 type=bpy
.types
.OperatorFileListElement
,
1643 loglevel
: IntProperty(
1645 description
="Log Level")
1647 import_pack_images
: BoolProperty(
1649 description
='Pack all images into .blend file',
1653 merge_vertices
: BoolProperty(
1654 name
='Merge Vertices',
1656 'The glTF format requires discontinuous normals, UVs, and '
1657 'other vertex attributes to be stored as separate vertices, '
1658 'as required for rendering on typical graphics hardware. '
1659 'This option attempts to combine co-located vertices where possible. '
1660 'Currently cannot combine verts with different normals'
1665 import_shading
: EnumProperty(
1667 items
=(("NORMALS", "Use Normal Data", ""),
1668 ("FLAT", "Flat Shading", ""),
1669 ("SMOOTH", "Smooth Shading", "")),
1670 description
="How normals are computed during import",
1673 bone_heuristic
: EnumProperty(
1676 ("BLENDER", "Blender (best for import/export round trip)",
1677 "Good for re-importing glTFs exported from Blender, "
1678 "and re-exporting glTFs to glTFs after Blender editing. "
1679 "Bone tips are placed on their local +Y axis (in glTF space)"),
1680 ("TEMPERANCE", "Temperance (average)",
1681 "Decent all-around strategy. "
1682 "A bone with one child has its tip placed on the local axis "
1683 "closest to its child"),
1684 ("FORTUNE", "Fortune (may look better, less accurate)",
1685 "Might look better than Temperance, but also might have errors. "
1686 "A bone with one child has its tip placed at its child's root. "
1687 "Non-uniform scalings may get messed up though, so beware"),
1689 description
="Heuristic for placing bones. Tries to make bones pretty",
1693 guess_original_bind_pose
: BoolProperty(
1694 name
='Guess Original Bind Pose',
1696 'Try to guess the original bind pose for skinned meshes from '
1697 'the inverse bind matrices. '
1698 'When off, use default/rest pose as bind pose'
1703 import_webp_texture
: BoolProperty(
1704 name
='Import WebP textures',
1706 "If a texture exists in WebP format, "
1707 "loads the WebP texture instead of the fallback PNG/JPEG one"
1712 def draw(self
, context
):
1713 layout
= self
.layout
1715 layout
.use_property_split
= True
1716 layout
.use_property_decorate
= False # No animation.
1718 layout
.prop(self
, 'import_pack_images')
1719 layout
.prop(self
, 'merge_vertices')
1720 layout
.prop(self
, 'import_shading')
1721 layout
.prop(self
, 'guess_original_bind_pose')
1722 layout
.prop(self
, 'bone_heuristic')
1723 layout
.prop(self
, 'export_import_convert_lighting_mode')
1724 layout
.prop(self
, 'import_webp_texture')
1726 def invoke(self
, context
, event
):
1728 preferences
= bpy
.context
.preferences
1729 for addon_name
in preferences
.addons
.keys():
1731 if hasattr(sys
.modules
[addon_name
], 'glTF2ImportUserExtension') or hasattr(sys
.modules
[addon_name
], 'glTF2ImportUserExtensions'):
1732 importer_extension_panel_unregister_functors
.append(sys
.modules
[addon_name
].register_panel())
1736 self
.has_active_importer_extensions
= len(importer_extension_panel_unregister_functors
) > 0
1737 return ImportHelper
.invoke_popup(self
, context
)
1739 def execute(self
, context
):
1740 return self
.import_gltf2(context
)
1742 def import_gltf2(self
, context
):
1745 self
.set_debug_log()
1746 import_settings
= self
.as_keywords()
1748 user_extensions
= []
1751 preferences
= bpy
.context
.preferences
1752 for addon_name
in preferences
.addons
.keys():
1754 module
= sys
.modules
[addon_name
]
1757 if hasattr(module
, 'glTF2ImportUserExtension'):
1758 extension_ctor
= module
.glTF2ImportUserExtension
1759 user_extensions
.append(extension_ctor())
1760 import_settings
['import_user_extensions'] = user_extensions
1763 # Multiple file import
1765 dirname
= os
.path
.dirname(self
.filepath
)
1766 for file in self
.files
:
1767 path
= os
.path
.join(dirname
, file.name
)
1768 if self
.unit_import(path
, import_settings
) == {'FINISHED'}:
1772 # Single file import
1773 return self
.unit_import(self
.filepath
, import_settings
)
1775 def unit_import(self
, filename
, import_settings
):
1777 from .io
.imp
.gltf2_io_gltf
import glTFImporter
, ImportError
1778 from .blender
.imp
.gltf2_blender_gltf
import BlenderGlTF
1781 gltf_importer
= glTFImporter(filename
, import_settings
)
1782 gltf_importer
.read()
1783 gltf_importer
.checks()
1785 gltf_importer
.log
.info("Data are loaded, start creating Blender stuff")
1787 start_time
= time
.time()
1788 BlenderGlTF
.create(gltf_importer
)
1789 elapsed_s
= "{:.2f}s".format(time
.time() - start_time
)
1790 gltf_importer
.log
.info("glTF import finished in " + elapsed_s
)
1792 # Display popup log, if any
1793 for message_type
, message
in gltf_importer
.log
.messages():
1794 self
.report({message_type}
, message
)
1796 gltf_importer
.log
.flush()
1800 except ImportError as e
:
1801 self
.report({'ERROR'}, e
.args
[0])
1802 return {'CANCELLED'}
1804 def set_debug_log(self
):
1806 if bpy
.app
.debug_value
== 0: # Default values => Display all messages except debug ones
1807 self
.loglevel
= logging
.INFO
1808 elif bpy
.app
.debug_value
== 1:
1809 self
.loglevel
= logging
.WARNING
1810 elif bpy
.app
.debug_value
== 2:
1811 self
.loglevel
= logging
.ERROR
1812 elif bpy
.app
.debug_value
== 3:
1813 self
.loglevel
= logging
.CRITICAL
1814 elif bpy
.app
.debug_value
== 4:
1815 self
.loglevel
= logging
.DEBUG
1818 class GLTF2_filter_action(bpy
.types
.PropertyGroup
):
1819 keep
: bpy
.props
.BoolProperty(name
="Keep Animation")
1820 action
: bpy
.props
.PointerProperty(type=bpy
.types
.Action
)
1822 def gltf_variant_ui_update(self
, context
):
1823 from .blender
.com
.gltf2_blender_ui
import variant_register
, variant_unregister
1824 if self
.KHR_materials_variants_ui
is True:
1825 # register all needed types
1828 variant_unregister()
1830 def gltf_animation_ui_update(self
, context
):
1831 from .blender
.com
.gltf2_blender_ui
import anim_ui_register
, anim_ui_unregister
1832 if self
.animation_ui
is True:
1833 # register all needed types
1836 anim_ui_unregister()
1838 class GLTF_AddonPreferences(bpy
.types
.AddonPreferences
):
1839 bl_idname
= __package__
1841 settings_node_ui
: bpy
.props
.BoolProperty(
1843 description
="Displays glTF Material Output node in Shader Editor (Menu Add > Output)"
1846 KHR_materials_variants_ui
: bpy
.props
.BoolProperty(
1848 description
="Displays glTF UI to manage material variants",
1849 update
=gltf_variant_ui_update
1852 animation_ui
: bpy
.props
.BoolProperty(
1854 description
="Display glTF UI to manage animations",
1855 update
=gltf_animation_ui_update
1858 gltfpack_path_ui
: bpy
.props
.StringProperty(
1860 name
="glTFpack file path",
1861 description
="Path to gltfpack binary",
1865 allow_embedded_format
: bpy
.props
.BoolProperty(
1867 name
='Allow glTF Embedded format',
1868 description
="Allow glTF Embedded format"
1871 def draw(self
, context
):
1872 layout
= self
.layout
1874 row
.prop(self
, "settings_node_ui", text
="Shader Editor Add-ons")
1875 row
.prop(self
, "KHR_materials_variants_ui", text
="Material Variants")
1876 row
.prop(self
, "animation_ui", text
="Animation UI")
1878 row
.prop(self
, "gltfpack_path_ui", text
="Path to gltfpack")
1880 row
.prop(self
, "allow_embedded_format", text
="Allow glTF Embedded format")
1881 if self
.allow_embedded_format
:
1882 layout
.label(text
="This is the least efficient of the available forms, and should only be used when required.", icon
='ERROR')
1885 class IO_FH_gltf2(bpy
.types
.FileHandler
):
1886 bl_idname
= "IO_FH_gltf2"
1887 bl_label
= "glTF 2.0"
1888 bl_import_operator
= "import_scene.gltf"
1889 bl_export_operator
= "export_scene.gltf"
1890 bl_file_extensions
= ".glb;.gltf"
1893 def poll_drop(cls
, context
):
1894 return poll_file_object_drop(context
)
1897 def menu_func_import(self
, context
):
1898 self
.layout
.operator(ImportGLTF2
.bl_idname
, text
='glTF 2.0 (.glb/.gltf)')
1905 GLTF2_filter_action
,
1906 GLTF_AddonPreferences
1911 from .blender
.com
import gltf2_blender_ui
as blender_ui
1914 bpy
.utils
.register_class(c
)
1915 # bpy.utils.register_module(__name__)
1917 blender_ui
.register()
1918 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.KHR_materials_variants_ui
is True:
1919 blender_ui
.variant_register()
1920 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.animation_ui
is True:
1921 blender_ui
.anim_ui_register()
1923 # add to the export / import menu
1924 bpy
.types
.TOPBAR_MT_file_export
.append(menu_func_export
)
1925 bpy
.types
.TOPBAR_MT_file_import
.append(menu_func_import
)
1929 from .blender
.com
import gltf2_blender_ui
as blender_ui
1930 blender_ui
.unregister()
1931 if bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.KHR_materials_variants_ui
is True:
1932 blender_ui
.variant_unregister()
1935 bpy
.utils
.unregister_class(c
)
1936 for f
in exporter_extension_panel_unregister_functors
:
1938 exporter_extension_panel_unregister_functors
.clear()
1940 for f
in importer_extension_panel_unregister_functors
:
1942 importer_extension_panel_unregister_functors
.clear()
1944 # bpy.utils.unregister_module(__name__)
1946 # remove from the export / import menu
1947 bpy
.types
.TOPBAR_MT_file_export
.remove(menu_func_export
)
1948 bpy
.types
.TOPBAR_MT_file_import
.remove(menu_func_import
)