Skip to content

Commit 191d17b

Browse files
committed
GLTF: Allow controlling how external data is handled on export
1 parent bc19229 commit 191d17b

8 files changed

Lines changed: 189 additions & 78 deletions

modules/gltf/doc_classes/GLTFState.xml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@
169169
Returns an array of unique node names. This is used in both the import process and export process.
170170
</description>
171171
</method>
172+
<method name="is_text_file" qualifiers="const">
173+
<return type="bool" />
174+
<description>
175+
Returns [code]true[/code] if [member filename] indicates this is a text-based glTF file, meaning that it ends with [code]".gltf"[/code] (case insensitive). Returns [code]false[/code] with any other extension or for an empty filename (indicating this is a byte array in memory).
176+
</description>
177+
</method>
172178
<method name="set_accessors">
173179
<return type="void" />
174180
<param index="0" name="accessors" type="GLTFAccessor[]" />
@@ -286,6 +292,13 @@
286292
Sets the unique node names in the state. This is used in both the import process and export process.
287293
</description>
288294
</method>
295+
<method name="should_separate_resource_files" qualifiers="const">
296+
<return type="bool" />
297+
<description>
298+
Returns [code]true[/code] if resource files, such as images, should be separated into their own files. Returns [code]false[/code] if they should be embedded in the glTF file. This is determined by the [member external_data_mode] property.
299+
Extensions should call this method to determine if they should save their resources in separate files. For example, the [code]KHR_audio_emitter[/code] extension should use this to determine if it should save audio files in separate files such as [code].mp3[/code] files, or if it should embed them in the glTF file in buffer views. For example, any extension handling images should use this to determine if they should save images in separate files such as [code].png[/code] files, or if they should embed them in the glTF file in buffer views.
300+
</description>
301+
</method>
289302
</methods>
290303
<members>
291304
<member name="bake_fps" type="float" setter="set_bake_fps" getter="get_bake_fps" default="30.0">
@@ -301,6 +314,12 @@
301314
</member>
302315
<member name="create_animations" type="bool" setter="set_create_animations" getter="get_create_animations" default="true">
303316
</member>
317+
<member name="external_data_mode" type="int" setter="set_external_data_mode" getter="get_external_data_mode" enum="GLTFState.ExternalDataMode" default="0">
318+
When exporting a glTF file, this determines where external data, such as images and binary buffers, should be stored.
319+
The default value is [constant EXTERNAL_DATA_MODE_AUTOMATIC], which automatically determines if data should be embedded or separated based on the file extension used, embedding for [code].glb[/code] files and separating for [code].gltf[/code] files. If you want different behavior, you can set this to one of the [enum ExternalDataMode] values.
320+
Saving resources like images to their own files can be useful for destinations where you need access to these files separately. For example, if the exported glTF is added to the [code]res://[/code] folder of a Godot project, the default behavior of the Godot editor is to extract embedded images to their own files so they can be imported and compressed into GPU-optimized formats.
321+
Extensions should respect this setting by calling [method should_separate_resource_files] to determine if they should save their resources in separate files.
322+
</member>
304323
<member name="filename" type="String" setter="set_filename" getter="get_filename" default="&quot;&quot;">
305324
The file name associated with this glTF data. If it ends with [code].gltf[/code], this is text-based glTF, otherwise this is binary GLB. This will be set during import when appending from a file, and will be set during export when writing to a file. If writing to a buffer, this will be an empty string.
306325
</member>
@@ -331,6 +350,29 @@
331350
</member>
332351
</members>
333352
<constants>
353+
<constant name="EXTERNAL_DATA_MODE_AUTOMATIC" value="0" enum="ExternalDataMode">
354+
When exporting a glTF file, automatically determines if data should be embedded or separated based on the file extension used and if [member base_path] is valid. With this option, exporting a [code].gltf[/code] file with a valid [member base_path] will behave like [constant EXTERNAL_DATA_MODE_SEPARATE_ALL_FILES]. If exporting a [code].glb[/code] file, exporting to an in-memory buffer, or exporting with [member base_path] set to an empty string, this will behave like [constant EXTERNAL_DATA_MODE_EMBED_EVERYTHING].
355+
This option is suitable for most use cases. It behaves like Blender's "glTF Binary (.glb)" export option for [code].glb[/code] files, and like Blender's "glTF Separate (.gltf + .bin + textures)" export option for [code].gltf[/code] files.
356+
</constant>
357+
<constant name="EXTERNAL_DATA_MODE_EMBED_EVERYTHING" value="1" enum="ExternalDataMode">
358+
When exporting a glTF file, embeds all data in the glTF file, including images and binary buffers. For [code].glb[/code] files, this will use the binary blob chunk at the end of the file to store the data in buffer 0 (if present). For all other buffers, such as buffers in [code].gltf[/code] files, the data will be embedded as a base64-encoded string in the JSON of the buffer.
359+
This option is useful when you want a single self-contained file. It behaves like Blender's "glTF Binary (.glb)" export option for [code].glb[/code] files, and like Blender's "glTF Embedded (.gltf)" export option for [code].gltf[/code] files.
360+
[b]Note:[/b] This usually results in a single self-contained file, but this is not guaranteed. The glTF binary ([code].glb[/code]) format has a maximum file size of 4 GiB, so if the data exceeds that size, the buffer will be forced to save as a separate file.
361+
</constant>
362+
<constant name="EXTERNAL_DATA_MODE_SEPARATE_ALL_FILES" value="2" enum="ExternalDataMode">
363+
When exporting a glTF file, separates all files that can be saved in their own file formats into their own files, and also save all raw binary blobs, such as glTF buffers, into separate [code].bin[/code] files.
364+
This option is useful when having the glTF file's contents spread out over multiple files is desired, resulting in maximum human readability. It behaves like Blender's "glTF Separate (.gltf + .bin + textures)" export option.
365+
Extensions should respect this setting by calling [method should_separate_resource_files] to determine if they should save their resources in separate files.
366+
</constant>
367+
<constant name="EXTERNAL_DATA_MODE_SEPARATE_BINARY_BLOBS" value="3" enum="ExternalDataMode">
368+
When exporting a glTF file, separates all raw binary blobs, such as glTF buffers, into separate [code].bin[/code] files. Resources that can be saved in their own file formats, such as images, are embedded within glTF buffers, and are stored in the [code].bin[/code] files.
369+
This option is useful if you need efficient storage of binary data while also keeping the number of files low. In the typical case, this option will result in only two files: the glTF file and a single [code].bin[/code] file next to it.
370+
</constant>
371+
<constant name="EXTERNAL_DATA_MODE_SEPARATE_RESOURCE_FILES" value="4" enum="ExternalDataMode">
372+
When exporting a glTF file, separates all resources that can be saved in their own file formats into their own files, such as images. This option does not separate buffers, meaning that binary blob data without a file type, such as mesh data, animation data, skin/skeleton data, and so on, are still embedded in the glTF file.
373+
This option is useful if the exported glTF file is intended to be added to the project folder in a game engine, so that the game engine can import the resources files separately, and optionally use them separately. Otherwise, game engines may extract embedded resources to their own files, resulting in duplicate data in the project folder.
374+
Extensions should respect this setting by calling [method should_separate_resource_files] to determine if they should save their resources in separate files.
375+
</constant>
334376
<constant name="HANDLE_BINARY_IMAGE_MODE_DISCARD_TEXTURES" value="0" enum="HandleBinaryImageMode">
335377
When importing a glTF file with embedded binary images, discards all images and uses untextured materials in their place. Images stored as separate files in the [code]res://[/code] folder are not affected by this; those will be used as Godot imported them.
336378
</constant>

modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ void SceneExporterGLTFPlugin::_export_scene_as_gltf() {
113113
Ref<GLTFState> state;
114114
state.instantiate();
115115
state->set_copyright(_export_settings->get_copyright());
116+
state->set_external_data_mode(_export_settings->get_external_data_mode());
116117
int32_t flags = 0;
117118
flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
118119
state->set_bake_fps(_export_settings->get_bake_fps());

modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ void EditorSceneExporterGLTFSettings::_bind_methods() {
266266
ClassDB::bind_method(D_METHOD("get_bake_fps"), &EditorSceneExporterGLTFSettings::get_bake_fps);
267267
ClassDB::bind_method(D_METHOD("set_bake_fps", "bake_fps"), &EditorSceneExporterGLTFSettings::set_bake_fps);
268268
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_fps", PROPERTY_HINT_RANGE, "0.001,120,0.0001,or_greater"), "set_bake_fps", "get_bake_fps");
269+
270+
ClassDB::bind_method(D_METHOD("get_external_data_mode"), &EditorSceneExporterGLTFSettings::get_external_data_mode);
271+
ClassDB::bind_method(D_METHOD("set_external_data_mode", "external_data_mode"), &EditorSceneExporterGLTFSettings::set_external_data_mode);
272+
ADD_PROPERTY(PropertyInfo(Variant::INT, "external_data_mode", PROPERTY_HINT_ENUM, "Automatic,Embed Everything,Separate All Files,Separate Binary Blobs,Separate Resource Files"), "set_external_data_mode", "get_external_data_mode");
269273
}
270274

271275
double EditorSceneExporterGLTFSettings::get_bake_fps() const {

modules/gltf/editor/editor_scene_exporter_gltf_settings.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class EditorSceneExporterGLTFSettings : public RefCounted {
4040

4141
String _copyright;
4242
double _bake_fps = 30.0;
43+
GLTFState::ExternalDataMode _external_data_mode = GLTFState::EXTERNAL_DATA_MODE_AUTOMATIC;
4344

4445
protected:
4546
static void _bind_methods();
@@ -59,4 +60,7 @@ class EditorSceneExporterGLTFSettings : public RefCounted {
5960

6061
double get_bake_fps() const;
6162
void set_bake_fps(const double p_bake_fps);
63+
64+
GLTFState::ExternalDataMode get_external_data_mode() const { return _external_data_mode; }
65+
void set_external_data_mode(GLTFState::ExternalDataMode p_external_data_mode) { _external_data_mode = p_external_data_mode; }
6266
};

0 commit comments

Comments
 (0)