1 # SPDX-FileCopyrightText: 2018-2021 The glTF-Blender-IO authors
3 # SPDX-License-Identifier: Apache-2.0
13 from ...io
.com
.gltf2_io_debug
import print_console
, print_newline
14 from ...io
.exp
import gltf2_io_export
15 from ...io
.exp
import gltf2_io_draco_compression_extension
16 from ...io
.exp
.gltf2_io_user_extensions
import export_user_extensions
17 from ..com
import gltf2_blender_json
18 from . import gltf2_blender_gather
19 from .gltf2_blender_gltf2_exporter
import GlTF2Exporter
20 from .gltf2_blender_gltf2_exporter
import fix_json
23 def save(context
, export_settings
):
24 """Start the glTF 2.0 export and saves to content either to a .gltf or .glb file."""
25 if bpy
.context
.active_object
is not None:
26 if bpy
.context
.active_object
.mode
!= "OBJECT": # For linked object, you can't force OBJECT mode
27 bpy
.ops
.object.mode_set(mode
='OBJECT')
29 original_frame
= bpy
.context
.scene
.frame_current
30 if not export_settings
['gltf_current_frame']:
31 bpy
.context
.scene
.frame_set(0)
33 __notify_start(context
)
34 start_time
= time
.time()
35 pre_export_callbacks
= export_settings
["pre_export_callbacks"]
36 for callback
in pre_export_callbacks
:
37 callback(export_settings
)
39 json
, buffer = __export(export_settings
)
41 post_export_callbacks
= export_settings
["post_export_callbacks"]
42 for callback
in post_export_callbacks
:
43 callback(export_settings
)
44 __write_file(json
, buffer, export_settings
)
46 end_time
= time
.time()
47 __notify_end(context
, end_time
- start_time
)
49 if not export_settings
['gltf_current_frame']:
50 bpy
.context
.scene
.frame_set(int(original_frame
))
54 def __export(export_settings
):
55 exporter
= GlTF2Exporter(export_settings
)
56 __gather_gltf(exporter
, export_settings
)
57 buffer = __create_buffer(exporter
, export_settings
)
58 exporter
.finalize_images()
60 export_user_extensions('gather_gltf_extensions_hook', export_settings
, exporter
.glTF
)
61 exporter
.traverse_extensions()
63 # now that addons possibly add some fields in json, we can fix in needed
64 json
= fix_json(exporter
.glTF
.to_dict())
66 # Convert additional data if needed
67 if export_settings
['gltf_unused_textures'] is True:
68 additional_json_textures
= fix_json([i
.to_dict() for i
in exporter
.additional_data
.additional_textures
])
70 # Now that we have the final json, we can add the additional data
71 # We can not do that for all people, because we don't want this extra to become "a standard"
72 # So let's use the "extras" field filled by a user extension
74 export_user_extensions('gather_gltf_additional_textures_hook', export_settings
, json
, additional_json_textures
)
76 # if len(additional_json_textures) > 0:
77 # if json.get('extras') is None:
79 # json['extras']['additionalTextures'] = additional_json_textures
84 def __gather_gltf(exporter
, export_settings
):
85 active_scene_idx
, scenes
, animations
= gltf2_blender_gather
.gather_gltf2(export_settings
)
87 unused_skins
= export_settings
['vtree'].get_unused_skins()
89 if export_settings
['gltf_draco_mesh_compression']:
90 gltf2_io_draco_compression_extension
.encode_scene_primitives(scenes
, export_settings
)
91 exporter
.add_draco_extension()
93 export_user_extensions('gather_gltf_hook', export_settings
, active_scene_idx
, scenes
, animations
)
95 for idx
, scene
in enumerate(scenes
):
96 exporter
.add_scene(scene
, idx
==active_scene_idx
, export_settings
=export_settings
)
97 for animation
in animations
:
98 exporter
.add_animation(animation
)
99 exporter
.manage_gpu_instancing_nodes(export_settings
)
100 exporter
.traverse_unused_skins(unused_skins
)
101 exporter
.traverse_additional_textures()
102 exporter
.traverse_additional_images()
105 def __create_buffer(exporter
, export_settings
):
107 if export_settings
['gltf_format'] == 'GLB':
108 buffer = exporter
.finalize_buffer(export_settings
['gltf_filedirectory'], is_glb
=True)
110 if export_settings
['gltf_format'] == 'GLTF_EMBEDDED':
111 exporter
.finalize_buffer(export_settings
['gltf_filedirectory'])
113 exporter
.finalize_buffer(export_settings
['gltf_filedirectory'],
114 export_settings
['gltf_binaryfilename'])
118 def __postprocess_with_gltfpack(export_settings
):
120 gltfpack_binary_file_path
= bpy
.context
.preferences
.addons
['io_scene_gltf2'].preferences
.gltfpack_path_ui
122 gltf_file_path
= export_settings
['gltf_filepath']
123 gltf_file_base
= os
.path
.splitext(os
.path
.basename(gltf_file_path
))[0]
124 gltf_file_extension
= os
.path
.splitext(os
.path
.basename(gltf_file_path
))[1]
125 gltf_file_directory
= os
.path
.dirname(gltf_file_path
)
126 gltf_output_file_directory
= os
.path
.join(gltf_file_directory
, "gltfpacked")
127 if (os
.path
.exists(gltf_output_file_directory
) is False):
128 os
.makedirs(gltf_output_file_directory
)
130 gltf_input_file_path
= gltf_file_path
131 gltf_output_file_path
= os
.path
.join(gltf_output_file_directory
, gltf_file_base
+ gltf_file_extension
)
135 if (export_settings
['gltf_gltfpack_tc']):
136 options
.append("-tc")
138 if (export_settings
['gltf_gltfpack_tq']):
139 options
.append("-tq")
140 options
.append(f
"{export_settings['gltf_gltfpack_tq']}")
142 if (export_settings
['gltf_gltfpack_si'] != 1.0):
143 options
.append("-si")
144 options
.append(f
"{export_settings['gltf_gltfpack_si']}")
146 if (export_settings
['gltf_gltfpack_sa']):
147 options
.append("-sa")
149 if (export_settings
['gltf_gltfpack_slb']):
150 options
.append("-slb")
152 if (export_settings
['gltf_gltfpack_noq']):
153 options
.append("-noq")
155 options
.append("-vp")
156 options
.append(f
"{export_settings['gltf_gltfpack_vp']}")
157 options
.append("-vt")
158 options
.append(f
"{export_settings['gltf_gltfpack_vt']}")
159 options
.append("-vn")
160 options
.append(f
"{export_settings['gltf_gltfpack_vn']}")
161 options
.append("-vc")
162 options
.append(f
"{export_settings['gltf_gltfpack_vc']}")
164 match export_settings
['gltf_gltfpack_vpi']:
166 options
.append("-vpi")
168 options
.append("-vpn")
169 case
"Floating-point":
170 options
.append("-vpf")
173 parameters
.append("-i")
174 parameters
.append(gltf_input_file_path
)
175 parameters
.append("-o")
176 parameters
.append(gltf_output_file_path
)
179 subprocess
.run([gltfpack_binary_file_path
] + options
+ parameters
, check
=True)
180 except subprocess
.CalledProcessError
as e
:
181 print_console('ERROR', "Calling gltfpack was not successful")
183 def __write_file(json
, buffer, export_settings
):
185 gltf2_io_export
.save_gltf(
188 gltf2_blender_json
.BlenderJSONEncoder
,
190 if (export_settings
['gltf_use_gltfpack'] == True):
191 __postprocess_with_gltfpack(export_settings
)
193 except AssertionError as e
:
194 _
, _
, tb
= sys
.exc_info()
195 traceback
.print_tb(tb
) # Fixed format
196 tb_info
= traceback
.extract_tb(tb
)
198 filename
, line
, func
, text
= tbi
199 print_console('ERROR', 'An error occurred on line {} in statement {}'.format(line
, text
))
200 print_console('ERROR', str(e
))
204 def __notify_start(context
):
205 print_console('INFO', 'Starting glTF 2.0 export')
206 context
.window_manager
.progress_begin(0, 100)
207 context
.window_manager
.progress_update(0)
210 def __notify_end(context
, elapsed
):
211 print_console('INFO', 'Finished glTF 2.0 export in {} s'.format(elapsed
))
212 context
.window_manager
.progress_end()