diff options
Diffstat (limited to 'modules/gltf')
32 files changed, 1771 insertions, 1619 deletions
diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml index 3cd0f5c0f9..f313f4b28f 100644 --- a/modules/gltf/doc_classes/GLTFDocument.xml +++ b/modules/gltf/doc_classes/GLTFDocument.xml @@ -14,8 +14,9 @@ <param index="1" name="base_path" type="String" /> <param index="2" name="state" type="GLTFState" /> <param index="3" name="flags" type="int" default="0" /> - <param index="4" name="bake_fps" type="int" default="30" /> <description> + Takes a [PackedByteArray] defining a gLTF and returns a [GLTFState] object through the [param state] parameter. + [b]Note:[/b] The [param base_path] tells [method append_from_buffer] where to find dependencies and can be empty. </description> </method> <method name="append_from_file"> @@ -23,9 +24,10 @@ <param index="0" name="path" type="String" /> <param index="1" name="state" type="GLTFState" /> <param index="2" name="flags" type="int" default="0" /> - <param index="3" name="bake_fps" type="int" default="30" /> - <param index="4" name="base_path" type="String" default="""" /> + <param index="3" name="base_path" type="String" default="""" /> <description> + Takes a path to a gLTF file and returns a [GLTFState] object through the [param state] parameter. + [b]Note:[/b] The [param base_path] tells [method append_from_file] where to find dependencies and can be empty. </description> </method> <method name="append_from_scene"> @@ -33,21 +35,40 @@ <param index="0" name="node" type="Node" /> <param index="1" name="state" type="GLTFState" /> <param index="2" name="flags" type="int" default="0" /> - <param index="3" name="bake_fps" type="int" default="30" /> <description> + Takes a Godot Engine scene node and returns a [GLTFState] object through the [param state] parameter. </description> </method> <method name="generate_buffer"> <return type="PackedByteArray" /> <param index="0" name="state" type="GLTFState" /> <description> + Takes a [GLTFState] object through the [param state] parameter and returns a gLTF [PackedByteArray]. </description> </method> <method name="generate_scene"> <return type="Node" /> <param index="0" name="state" type="GLTFState" /> - <param index="1" name="bake_fps" type="int" default="30" /> + <param index="1" name="bake_fps" type="float" default="30" /> + <param index="2" name="trimming" type="bool" default="false" /> <description> + Takes a [GLTFState] object through the [param state] parameter and returns a Godot Engine scene node. + </description> + </method> + <method name="register_gltf_document_extension" qualifiers="static"> + <return type="void" /> + <param index="0" name="extension" type="GLTFDocumentExtension" /> + <param index="1" name="first_priority" type="bool" default="false" /> + <description> + Registers the given [GLTFDocumentExtension] instance with GLTFDocument. If [param first_priority] is true, this extension will be run first. Otherwise, it will be run last. + [b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode]. + </description> + </method> + <method name="unregister_gltf_document_extension" qualifiers="static"> + <return type="void" /> + <param index="0" name="extension" type="GLTFDocumentExtension" /> + <description> + Unregisters the given [GLTFDocumentExtension] instance. </description> </method> <method name="write_to_filesystem"> @@ -55,11 +76,9 @@ <param index="0" name="state" type="GLTFState" /> <param index="1" name="path" type="String" /> <description> + Takes a [GLTFState] object through the [param state] parameter and writes a glTF file to the filesystem. + [b]Note:[/b] The extension of the glTF file determines if it is a .glb binary file or a .gltf file. </description> </method> </methods> - <members> - <member name="extensions" type="GLTFDocumentExtension[]" setter="set_extensions" getter="get_extensions" default="[]"> - </member> - </members> </class> diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml index 936794976d..6004de32f1 100644 --- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml +++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml @@ -5,10 +5,22 @@ </brief_description> <description> Extends the functionality of the [GLTFDocument] class by allowing you to run arbitrary code at various stages of GLTF import or export. + To use, make a new class extending GLTFDocumentExtension, override any methods you need, make an instance of your class, and register it using [method GLTFDocument.register_gltf_document_extension]. + [b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode]. </description> <tutorials> </tutorials> <methods> + <method name="_convert_scene_node" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="gltf_node" type="GLTFNode" /> + <param index="2" name="scene_node" type="Node" /> + <description> + Part of the export process. This method is run after [method _export_preflight] and before [method _export_node]. + Runs when converting the data from a Godot scene node. This method can be used to process the Godot scene node data into a format that can be used by [method _export_node]. + </description> + </method> <method name="_export_node" qualifiers="virtual"> <return type="int" /> <param index="0" name="state" type="GLTFState" /> @@ -16,23 +28,41 @@ <param index="2" name="json" type="Dictionary" /> <param index="3" name="node" type="Node" /> <description> + Part of the export process. This method is run after [method _convert_scene_node] and before [method _export_post]. + This method can be used to modify the final JSON of each node. </description> </method> <method name="_export_post" qualifiers="virtual"> <return type="int" /> <param index="0" name="state" type="GLTFState" /> <description> + Part of the export process. This method is run last, after all other parts of the export process. + This method can be used to modify the final JSON of the generated GLTF file. </description> </method> <method name="_export_preflight" qualifiers="virtual"> <return type="int" /> - <param index="0" name="root" type="Node" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="root" type="Node" /> + <description> + Part of the export process. This method is run first, before all other parts of the export process. + The return value is used to determine if this [GLTFDocumentExtension] instance should be used for exporting a given GLTF file. If [constant OK], the export will use this [GLTFDocumentExtension] instance. If not overridden, [constant OK] is returned. + </description> + </method> + <method name="_generate_scene_node" qualifiers="virtual"> + <return type="Node3D" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="gltf_node" type="GLTFNode" /> + <param index="2" name="scene_parent" type="Node" /> <description> + Part of the import process. This method is run after [method _parse_node_extensions] and before [method _import_post_parse]. + Runs when generating a Godot scene node from a GLTFNode. The returned node will be added to the scene tree. Multiple nodes can be generated in this step if they are added as a child of the returned node. </description> </method> <method name="_get_supported_extensions" qualifiers="virtual"> <return type="PackedStringArray" /> <description> + Part of the import process. This method is run after [method _import_preflight] and before [method _parse_node_extensions]. Returns an array of the GLTF extensions supported by this GLTFDocumentExtension class. This is used to validate if a GLTF file with required extensions can be loaded. </description> </method> @@ -43,6 +73,8 @@ <param index="2" name="json" type="Dictionary" /> <param index="3" name="node" type="Node" /> <description> + Part of the import process. This method is run after [method _import_post_parse] and before [method _import_post]. + This method can be used to make modifications to each of the generated Godot scene nodes. </description> </method> <method name="_import_post" qualifiers="virtual"> @@ -50,18 +82,35 @@ <param index="0" name="state" type="GLTFState" /> <param index="1" name="root" type="Node" /> <description> + Part of the import process. This method is run last, after all other parts of the import process. + This method can be used to modify the final Godot scene generated by the import process. </description> </method> <method name="_import_post_parse" qualifiers="virtual"> <return type="int" /> <param index="0" name="state" type="GLTFState" /> <description> + Part of the import process. This method is run after [method _generate_scene_node] and before [method _import_node]. + This method can be used to modify any of the data imported so far, including any scene nodes, before running the final per-node import step. </description> </method> <method name="_import_preflight" qualifiers="virtual"> <return type="int" /> <param index="0" name="state" type="GLTFState" /> + <param index="1" name="extensions" type="PackedStringArray" /> + <description> + Part of the import process. This method is run first, before all other parts of the import process. + The return value is used to determine if this [GLTFDocumentExtension] instance should be used for importing a given GLTF file. If [constant OK], the import will use this [GLTFDocumentExtension] instance. If not overridden, [constant OK] is returned. + </description> + </method> + <method name="_parse_node_extensions" qualifiers="virtual"> + <return type="int" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="gltf_node" type="GLTFNode" /> + <param index="2" name="extensions" type="Dictionary" /> <description> + Part of the import process. This method is run after [method _get_supported_extensions] and before [method _generate_scene_node]. + Runs when parsing the node extensions of a GLTFNode. This method can be used to process the extension JSON data into a format that can be used by [method _generate_scene_node]. The return value should be a member of the [enum Error] enum. </description> </method> </methods> diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index d0740cf7ca..9a554a0d49 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -66,7 +66,7 @@ </description> </method> <method name="get_materials"> - <return type="BaseMaterial3D[]" /> + <return type="Material[]" /> <description> </description> </method> @@ -169,7 +169,7 @@ </method> <method name="set_materials"> <return type="void" /> - <param index="0" name="materials" type="BaseMaterial3D[]" /> + <param index="0" name="materials" type="Material[]" /> <description> </description> </method> diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp index 95db1c0965..fe63afcc56 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp +++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp @@ -33,18 +33,10 @@ #include "editor_scene_exporter_gltf_plugin.h" #include "../gltf_document.h" -#include "../gltf_state.h" -#include "core/config/project_settings.h" -#include "core/error/error_list.h" -#include "core/object/object.h" -#include "core/templates/vector.h" #include "editor/editor_file_dialog.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "scene/3d/mesh_instance_3d.h" -#include "scene/gui/check_box.h" -#include "scene/main/node.h" String SceneExporterGLTFPlugin::get_name() const { return "ConvertGLTF2"; @@ -85,7 +77,7 @@ void SceneExporterGLTFPlugin::_gltf2_dialog_action(String p_file) { state.instantiate(); int32_t flags = 0; flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; - Error err = doc->append_from_scene(root, state, flags, 30.0f); + Error err = doc->append_from_scene(root, state, flags); if (err != OK) { ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err))); } diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h index 5af46bc752..66fd27b449 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h +++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h @@ -36,6 +36,8 @@ #include "editor/editor_plugin.h" #include "editor_scene_importer_gltf.h" +class EditorFileDialog; + class SceneExporterGLTFPlugin : public EditorPlugin { GDCLASS(SceneExporterGLTFPlugin, EditorPlugin); diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 20c9508474..4dafa746bc 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -33,7 +33,6 @@ #ifdef TOOLS_ENABLED #include "../gltf_document.h" -#include "../gltf_state.h" #include "core/config/project_settings.h" #include "editor/editor_file_dialog.h" @@ -41,8 +40,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "main/main.h" -#include "scene/main/node.h" -#include "scene/resources/animation.h" +#include "scene/gui/line_edit.h" #ifdef WINDOWS_ENABLED // Code by Pedro Estebanez (https://github.com/godotengine/godot/pull/59766) @@ -58,7 +56,7 @@ void EditorSceneFormatImporterBlend::get_extensions(List<String> *r_extensions) } Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags, - const HashMap<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) { // Get global paths for source and sink. @@ -227,14 +225,14 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) { base_dir = sink.get_base_dir(); } - Error err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, p_bake_fps, base_dir); + Error err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, base_dir); if (err != OK) { if (r_err) { *r_err = FAILED; } return nullptr; } - return gltf->generate_scene(state, p_bake_fps); + return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]); } Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index a1485ff82e..fe687f19fc 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -66,7 +66,7 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const HashMap<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err = nullptr) override; virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) override; diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp index 017a44cccf..27e0052c1a 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.cpp +++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp @@ -33,12 +33,10 @@ #ifdef TOOLS_ENABLED #include "../gltf_document.h" -#include "../gltf_state.h" #include "core/config/project_settings.h" #include "editor/editor_settings.h" -#include "scene/main/node.h" -#include "scene/resources/animation.h" +#include "main/main.h" uint32_t EditorSceneFormatImporterFBX::get_import_flags() const { return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION; @@ -49,7 +47,7 @@ void EditorSceneFormatImporterFBX::get_extensions(List<String> *r_extensions) co } Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t p_flags, - const HashMap<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) { // Get global paths for source and sink. @@ -95,14 +93,14 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t Ref<GLTFState> state; state.instantiate(); print_verbose(vformat("glTF path: %s", sink)); - Error err = gltf->append_from_file(sink, state, p_flags, p_bake_fps); + Error err = gltf->append_from_file(sink, state, p_flags); if (err != OK) { if (r_err) { *r_err = FAILED; } return nullptr; } - return gltf->generate_scene(state, p_bake_fps); + return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]); } Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation, @@ -114,4 +112,30 @@ void EditorSceneFormatImporterFBX::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) { } +bool EditorFileSystemImportFormatSupportQueryFBX::is_active() const { + String fbx2gltf_path = EDITOR_GET("filesystem/import/fbx/fbx2gltf_path"); + return !FileAccess::exists(fbx2gltf_path); +} + +Vector<String> EditorFileSystemImportFormatSupportQueryFBX::get_file_extensions() const { + Vector<String> ret; + ret.push_back("fbx"); + return ret; +} + +bool EditorFileSystemImportFormatSupportQueryFBX::query() { + FBXImporterManager::get_singleton()->show_dialog(true); + + while (true) { + OS::get_singleton()->delay_usec(1); + DisplayServer::get_singleton()->process_events(); + Main::iteration(); + if (!FBXImporterManager::get_singleton()->is_visible()) { + break; + } + } + + return false; +} + #endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h index b0039b1c8f..82179cc460 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.h +++ b/modules/gltf/editor/editor_scene_importer_fbx.h @@ -33,6 +33,8 @@ #ifdef TOOLS_ENABLED +#include "editor/editor_file_system.h" +#include "editor/fbx_importer_manager.h" #include "editor/import/resource_importer_scene.h" class Animation; @@ -45,7 +47,7 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const HashMap<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err = nullptr) override; virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) override; @@ -53,6 +55,15 @@ public: const HashMap<StringName, Variant> &p_options) override; }; +class EditorFileSystemImportFormatSupportQueryFBX : public EditorFileSystemImportFormatSupportQuery { + GDCLASS(EditorFileSystemImportFormatSupportQueryFBX, EditorFileSystemImportFormatSupportQuery); + +public: + virtual bool is_active() const override; + virtual Vector<String> get_file_extensions() const override; + virtual bool query() override; +}; + #endif // TOOLS_ENABLED #endif // EDITOR_SCENE_IMPORTER_FBX_H diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp index 161808aade..bd1ba85abf 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp @@ -33,9 +33,6 @@ #include "editor_scene_importer_gltf.h" #include "../gltf_document.h" -#include "../gltf_state.h" - -#include "scene/resources/animation.h" uint32_t EditorSceneFormatImporterGLTF::get_import_flags() const { return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION; @@ -47,13 +44,13 @@ void EditorSceneFormatImporterGLTF::get_extensions(List<String> *r_extensions) c } Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, - const HashMap<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) { Ref<GLTFDocument> doc; doc.instantiate(); Ref<GLTFState> state; state.instantiate(); - Error err = doc->append_from_file(p_path, state, p_flags, p_bake_fps); + Error err = doc->append_from_file(p_path, state, p_flags); if (err != OK) { if (r_err) { *r_err = err; @@ -63,7 +60,12 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t if (p_options.has("animation/import")) { state->set_create_animations(bool(p_options["animation/import"])); } - return doc->generate_scene(state, p_bake_fps); + + if (p_options.has("animation/trimming")) { + return doc->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]); + } else { + return doc->generate_scene(state, (float)p_options["animation/fps"], false); + } } #endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h index b17a1e4eaa..c0582b26c1 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.h +++ b/modules/gltf/editor/editor_scene_importer_gltf.h @@ -33,9 +33,6 @@ #ifdef TOOLS_ENABLED -#include "../gltf_document_extension.h" -#include "../gltf_state.h" - #include "editor/import/resource_importer_scene.h" class Animation; @@ -48,7 +45,7 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const HashMap<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err = nullptr) override; }; diff --git a/modules/gltf/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp index 713779712c..630a62ba5c 100644 --- a/modules/gltf/gltf_document_extension.cpp +++ b/modules/gltf/extensions/gltf_document_extension.cpp @@ -31,35 +31,50 @@ #include "gltf_document_extension.h" void GLTFDocumentExtension::_bind_methods() { + // Import process. + GDVIRTUAL_BIND(_import_preflight, "state", "extensions"); GDVIRTUAL_BIND(_get_supported_extensions); - GDVIRTUAL_BIND(_import_preflight, "state"); + GDVIRTUAL_BIND(_parse_node_extensions, "state", "gltf_node", "extensions"); + GDVIRTUAL_BIND(_generate_scene_node, "state", "gltf_node", "scene_parent"); GDVIRTUAL_BIND(_import_post_parse, "state"); GDVIRTUAL_BIND(_import_node, "state", "gltf_node", "json", "node"); GDVIRTUAL_BIND(_import_post, "state", "root"); - GDVIRTUAL_BIND(_export_preflight, "root"); + // Export process. + GDVIRTUAL_BIND(_export_preflight, "state", "root"); + GDVIRTUAL_BIND(_convert_scene_node, "state", "gltf_node", "scene_node"); GDVIRTUAL_BIND(_export_node, "state", "gltf_node", "json", "node"); GDVIRTUAL_BIND(_export_post, "state"); } +// Import process. +Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) { + ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); + int err = OK; + GDVIRTUAL_CALL(_import_preflight, p_state, p_extensions, err); + return Error(err); +} + Vector<String> GLTFDocumentExtension::get_supported_extensions() { Vector<String> ret; GDVIRTUAL_CALL(_get_supported_extensions, ret); return ret; } -Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) { - ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); +Error GLTFDocumentExtension::parse_node_extensions(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &p_extensions) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER); int err = OK; - GDVIRTUAL_CALL(_import_post, p_state, p_root, err); + GDVIRTUAL_CALL(_parse_node_extensions, p_state, p_gltf_node, p_extensions, err); return Error(err); } -Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state) { - ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); - int err = OK; - GDVIRTUAL_CALL(_import_preflight, p_state, err); - return Error(err); +Node3D *GLTFDocumentExtension::generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) { + ERR_FAIL_NULL_V(p_state, nullptr); + ERR_FAIL_NULL_V(p_gltf_node, nullptr); + ERR_FAIL_NULL_V(p_scene_parent, nullptr); + Node3D *ret_node = nullptr; + GDVIRTUAL_CALL(_generate_scene_node, p_state, p_gltf_node, p_scene_parent, ret_node); + return ret_node; } Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) { @@ -69,28 +84,38 @@ Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) { return Error(err); } -Error GLTFDocumentExtension::export_post(Ref<GLTFState> p_state) { +Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER); int err = OK; - GDVIRTUAL_CALL(_export_post, p_state, err); + GDVIRTUAL_CALL(_import_node, p_state, p_gltf_node, r_dict, p_node, err); return Error(err); } -Error GLTFDocumentExtension::export_preflight(Node *p_root) { + +Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) { ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); int err = OK; - GDVIRTUAL_CALL(_export_preflight, p_root, err); + GDVIRTUAL_CALL(_import_post, p_state, p_root, err); return Error(err); } -Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) { - ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); - ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER); - ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER); +// Export process. +Error GLTFDocumentExtension::export_preflight(Ref<GLTFState> p_state, Node *p_root) { + ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); int err = OK; - GDVIRTUAL_CALL(_import_node, p_state, p_gltf_node, r_dict, p_node, err); + GDVIRTUAL_CALL(_export_preflight, p_state, p_root, err); return Error(err); } +void GLTFDocumentExtension::convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node) { + ERR_FAIL_NULL(p_state); + ERR_FAIL_NULL(p_gltf_node); + ERR_FAIL_NULL(p_scene_node); + GDVIRTUAL_CALL(_convert_scene_node, p_state, p_gltf_node, p_scene_node); +} + Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER); @@ -99,3 +124,10 @@ Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p GDVIRTUAL_CALL(_export_node, p_state, p_gltf_node, r_dict, p_node, err); return Error(err); } + +Error GLTFDocumentExtension::export_post(Ref<GLTFState> p_state) { + ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); + int err = OK; + GDVIRTUAL_CALL(_export_post, p_state, err); + return Error(err); +} diff --git a/modules/gltf/gltf_document_extension.h b/modules/gltf/extensions/gltf_document_extension.h index d4bb3993dc..66cb9a3c33 100644 --- a/modules/gltf/gltf_document_extension.h +++ b/modules/gltf/extensions/gltf_document_extension.h @@ -31,8 +31,7 @@ #ifndef GLTF_DOCUMENT_EXTENSION_H #define GLTF_DOCUMENT_EXTENSION_H -#include "gltf_state.h" -#include "structures/gltf_node.h" +#include "../gltf_state.h" class GLTFDocumentExtension : public Resource { GDCLASS(GLTFDocumentExtension, Resource); @@ -41,20 +40,31 @@ protected: static void _bind_methods(); public: + // Import process. + virtual Error import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions); virtual Vector<String> get_supported_extensions(); - virtual Error import_preflight(Ref<GLTFState> p_state); + virtual Error parse_node_extensions(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &p_extensions); + virtual Node3D *generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent); virtual Error import_post_parse(Ref<GLTFState> p_state); - virtual Error export_post(Ref<GLTFState> p_state); - virtual Error import_post(Ref<GLTFState> p_state, Node *p_node); - virtual Error export_preflight(Node *p_state); virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node); + virtual Error import_post(Ref<GLTFState> p_state, Node *p_node); + // Export process. + virtual Error export_preflight(Ref<GLTFState> p_state, Node *p_root); + virtual void convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node); virtual Error export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node); + virtual Error export_post(Ref<GLTFState> p_state); + + // Import process. + GDVIRTUAL2R(int, _import_preflight, Ref<GLTFState>, Vector<String>); GDVIRTUAL0R(Vector<String>, _get_supported_extensions); - GDVIRTUAL1R(int, _import_preflight, Ref<GLTFState>); + GDVIRTUAL3R(int, _parse_node_extensions, Ref<GLTFState>, Ref<GLTFNode>, Dictionary); + GDVIRTUAL3R(Node3D *, _generate_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *); GDVIRTUAL1R(int, _import_post_parse, Ref<GLTFState>); GDVIRTUAL4R(int, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *); GDVIRTUAL2R(int, _import_post, Ref<GLTFState>, Node *); - GDVIRTUAL1R(int, _export_preflight, Node *); + // Export process. + GDVIRTUAL2R(int, _export_preflight, Ref<GLTFState>, Node *); + GDVIRTUAL3(_convert_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *); GDVIRTUAL4R(int, _export_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *); GDVIRTUAL1R(int, _export_post, Ref<GLTFState>); }; diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp index 1620900a04..cfa498af65 100644 --- a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp +++ b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp @@ -30,9 +30,7 @@ #include "gltf_document_extension_convert_importer_mesh.h" -#include "gltf_state.h" - -#include "core/error/error_macros.h" +#include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/resources/importer_mesh.h" diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.h b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h index 00e664e73f..4fbfa0e066 100644 --- a/modules/gltf/gltf_document_extension_convert_importer_mesh.h +++ b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h @@ -33,10 +33,6 @@ #include "gltf_document_extension.h" -#include "scene/3d/importer_mesh_instance_3d.h" -#include "scene/3d/mesh_instance_3d.h" -#include "scene/resources/importer_mesh.h" - class GLTFDocumentExtensionConvertImporterMesh : public GLTFDocumentExtension { GDCLASS(GLTFDocumentExtensionConvertImporterMesh, GLTFDocumentExtension); diff --git a/modules/gltf/extensions/gltf_light.cpp b/modules/gltf/extensions/gltf_light.cpp index d00bead61c..0379c62c9d 100644 --- a/modules/gltf/extensions/gltf_light.cpp +++ b/modules/gltf/extensions/gltf_light.cpp @@ -30,6 +30,8 @@ #include "gltf_light.h" +#include "scene/3d/light_3d.h" + void GLTFLight::_bind_methods() { ClassDB::bind_static_method("GLTFLight", D_METHOD("from_node", "light_node"), &GLTFLight::from_node); ClassDB::bind_method(D_METHOD("to_node"), &GLTFLight::to_node); diff --git a/modules/gltf/extensions/gltf_light.h b/modules/gltf/extensions/gltf_light.h index 04980e144c..85284f1d0e 100644 --- a/modules/gltf/extensions/gltf_light.h +++ b/modules/gltf/extensions/gltf_light.h @@ -31,9 +31,9 @@ #ifndef GLTF_LIGHT_H #define GLTF_LIGHT_H -#include "core/config/engine.h" #include "core/io/resource.h" -#include "scene/3d/light_3d.h" + +class Light3D; // https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_lights_punctual diff --git a/modules/gltf/extensions/gltf_spec_gloss.cpp b/modules/gltf/extensions/gltf_spec_gloss.cpp index 83af91bfcc..0645f31e01 100644 --- a/modules/gltf/extensions/gltf_spec_gloss.cpp +++ b/modules/gltf/extensions/gltf_spec_gloss.cpp @@ -30,6 +30,8 @@ #include "gltf_spec_gloss.h" +#include "core/io/image.h" + void GLTFSpecGloss::_bind_methods() { ClassDB::bind_method(D_METHOD("get_diffuse_img"), &GLTFSpecGloss::get_diffuse_img); ClassDB::bind_method(D_METHOD("set_diffuse_img", "diffuse_img"), &GLTFSpecGloss::set_diffuse_img); diff --git a/modules/gltf/extensions/gltf_spec_gloss.h b/modules/gltf/extensions/gltf_spec_gloss.h index 2b4d3ee609..56474acd03 100644 --- a/modules/gltf/extensions/gltf_spec_gloss.h +++ b/modules/gltf/extensions/gltf_spec_gloss.h @@ -31,9 +31,10 @@ #ifndef GLTF_SPEC_GLOSS_H #define GLTF_SPEC_GLOSS_H -#include "core/io/image.h" #include "core/io/resource.h" +class Image; + // KHR_materials_pbrSpecularGlossiness is an archived GLTF extension. // This means that it is deprecated and not recommended for new files. // However, it is still supported for loading old files. diff --git a/modules/gltf/gltf_defines.h b/modules/gltf/gltf_defines.h index 23bf33869e..7b990e6573 100644 --- a/modules/gltf/gltf_defines.h +++ b/modules/gltf/gltf_defines.h @@ -36,9 +36,10 @@ // Godot classes used by GLTF headers. class BoneAttachment3D; class CSGShape3D; -class DirectionalLight3D; class GridMap; +class ImporterMeshInstance3D; class Light3D; +class MeshInstance3D; class MultiMeshInstance3D; class Skeleton3D; class Skin; diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 99803ed05d..d858f76b28 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -31,33 +31,23 @@ #include "gltf_document.h" #include "extensions/gltf_spec_gloss.h" -#include "gltf_document_extension.h" -#include "gltf_document_extension_convert_importer_mesh.h" -#include "gltf_state.h" #include "core/crypto/crypto_core.h" -#include "core/error/error_macros.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" #include "core/io/file_access_memory.h" #include "core/io/json.h" #include "core/io/stream_peer.h" #include "core/math/disjoint_set.h" -#include "core/math/vector2.h" -#include "core/variant/dictionary.h" -#include "core/variant/typed_array.h" -#include "core/variant/variant.h" #include "core/version.h" #include "drivers/png/png_driver_common.h" -#include "scene/2d/node_2d.h" +#include "scene/3d/bone_attachment_3d.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/importer_mesh_instance_3d.h" +#include "scene/3d/light_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/multimesh_instance_3d.h" -#include "scene/3d/node_3d.h" -#include "scene/animation/animation_player.h" -#include "scene/resources/importer_mesh.h" -#include "scene/resources/material.h" -#include "scene/resources/mesh.h" -#include "scene/resources/multimesh.h" +#include "scene/resources/skin.h" #include "scene/resources/surface_tool.h" #include "modules/modules_enabled.gen.h" // For csg, gridmap. @@ -113,148 +103,147 @@ static Ref<ImporterMesh> _mesh_to_importer_mesh(Ref<Mesh> p_mesh) { return importer_mesh; } -Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) { - if (!state->buffers.size()) { - state->buffers.push_back(Vector<uint8_t>()); +Error GLTFDocument::_serialize(Ref<GLTFState> p_state, const String &p_path) { + if (!p_state->buffers.size()) { + p_state->buffers.push_back(Vector<uint8_t>()); } /* STEP CONVERT MESH INSTANCES */ - _convert_mesh_instances(state); + _convert_mesh_instances(p_state); /* STEP SERIALIZE CAMERAS */ - Error err = _serialize_cameras(state); + Error err = _serialize_cameras(p_state); if (err != OK) { return Error::FAILED; } /* STEP 3 CREATE SKINS */ - err = _serialize_skins(state); + err = _serialize_skins(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE MESHES (we have enough info now) */ - err = _serialize_meshes(state); + err = _serialize_meshes(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE TEXTURES */ - err = _serialize_materials(state); + err = _serialize_materials(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE TEXTURE SAMPLERS */ - err = _serialize_texture_samplers(state); + err = _serialize_texture_samplers(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE ANIMATIONS */ - err = _serialize_animations(state); + err = _serialize_animations(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE ACCESSORS */ - err = _encode_accessors(state); + err = _encode_accessors(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE IMAGES */ - err = _serialize_images(state, p_path); + err = _serialize_images(p_state, p_path); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE TEXTURES */ - err = _serialize_textures(state); + err = _serialize_textures(p_state); if (err != OK) { return Error::FAILED; } - for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) { - state->buffer_views.write[i]->buffer = 0; + for (GLTFBufferViewIndex i = 0; i < p_state->buffer_views.size(); i++) { + p_state->buffer_views.write[i]->buffer = 0; } /* STEP SERIALIZE BUFFER VIEWS */ - err = _encode_buffer_views(state); + err = _encode_buffer_views(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE NODES */ - err = _serialize_nodes(state); + err = _serialize_nodes(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE SCENE */ - err = _serialize_scenes(state); + err = _serialize_scenes(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE LIGHTS */ - err = _serialize_lights(state); + err = _serialize_lights(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE EXTENSIONS */ - err = _serialize_gltf_extensions(state); + err = _serialize_gltf_extensions(p_state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE VERSION */ - err = _serialize_version(state); + err = _serialize_version(p_state); if (err != OK) { return Error::FAILED; } - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); - err = ext->export_post(state); + err = ext->export_post(p_state); ERR_FAIL_COND_V(err != OK, err); } return OK; } -Error GLTFDocument::_serialize_gltf_extensions(Ref<GLTFState> state) const { - Vector<String> extensions_used = state->extensions_used; - Vector<String> extensions_required = state->extensions_required; - if (!state->lights.is_empty()) { +Error GLTFDocument::_serialize_gltf_extensions(Ref<GLTFState> p_state) const { + Vector<String> extensions_used = p_state->extensions_used; + Vector<String> extensions_required = p_state->extensions_required; + if (!p_state->lights.is_empty()) { extensions_used.push_back("KHR_lights_punctual"); } - if (state->use_khr_texture_transform) { + if (p_state->use_khr_texture_transform) { extensions_used.push_back("KHR_texture_transform"); extensions_required.push_back("KHR_texture_transform"); } if (!extensions_used.is_empty()) { extensions_used.sort(); - state->json["extensionsUsed"] = extensions_used; + p_state->json["extensionsUsed"] = extensions_used; } if (!extensions_required.is_empty()) { extensions_required.sort(); - state->json["extensionsRequired"] = extensions_required; + p_state->json["extensionsRequired"] = extensions_required; } return OK; } -Error GLTFDocument::_serialize_scenes(Ref<GLTFState> state) { +Error GLTFDocument::_serialize_scenes(Ref<GLTFState> p_state) { Array scenes; const int loaded_scene = 0; - state->json["scene"] = loaded_scene; + p_state->json["scene"] = loaded_scene; - if (state->nodes.size()) { + if (p_state->nodes.size()) { Dictionary s; - if (!state->scene_name.is_empty()) { - s["name"] = state->scene_name; + if (!p_state->scene_name.is_empty()) { + s["name"] = p_state->scene_name; } Array nodes; @@ -262,21 +251,21 @@ Error GLTFDocument::_serialize_scenes(Ref<GLTFState> state) { s["nodes"] = nodes; scenes.push_back(s); } - state->json["scenes"] = scenes; + p_state->json["scenes"] = scenes; return OK; } -Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) { +Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> p_state) { Error err; - Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); - if (f.is_null()) { + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err); + if (file.is_null()) { return err; } Vector<uint8_t> array; - array.resize(f->get_length()); - f->get_buffer(array.ptrw(), array.size()); + array.resize(file->get_length()); + file->get_buffer(array.ptrw(), array.size()); String text; text.parse_utf8((const char *)array.ptr(), array.size()); @@ -286,26 +275,26 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) { _err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT); return err; } - state->json = json.get_data(); + p_state->json = json.get_data(); return OK; } -Error GLTFDocument::_parse_glb(Ref<FileAccess> f, Ref<GLTFState> state) { - ERR_FAIL_NULL_V(f, ERR_INVALID_PARAMETER); - ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(f->get_position() != 0, ERR_FILE_CANT_READ); - uint32_t magic = f->get_32(); +Error GLTFDocument::_parse_glb(Ref<FileAccess> p_file, Ref<GLTFState> p_state) { + ERR_FAIL_NULL_V(p_file, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(p_file->get_position() != 0, ERR_FILE_CANT_READ); + uint32_t magic = p_file->get_32(); ERR_FAIL_COND_V(magic != 0x46546C67, ERR_FILE_UNRECOGNIZED); //glTF - f->get_32(); // version - f->get_32(); // length - uint32_t chunk_length = f->get_32(); - uint32_t chunk_type = f->get_32(); + p_file->get_32(); // version + p_file->get_32(); // length + uint32_t chunk_length = p_file->get_32(); + uint32_t chunk_type = p_file->get_32(); ERR_FAIL_COND_V(chunk_type != 0x4E4F534A, ERR_PARSE_ERROR); //JSON Vector<uint8_t> json_data; json_data.resize(chunk_length); - uint32_t len = f->get_buffer(json_data.ptrw(), chunk_length); + uint32_t len = p_file->get_buffer(json_data.ptrw(), chunk_length); ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT); String text; @@ -318,21 +307,21 @@ Error GLTFDocument::_parse_glb(Ref<FileAccess> f, Ref<GLTFState> state) { return err; } - state->json = json.get_data(); + p_state->json = json.get_data(); //data? - chunk_length = f->get_32(); - chunk_type = f->get_32(); + chunk_length = p_file->get_32(); + chunk_type = p_file->get_32(); - if (f->eof_reached()) { + if (p_file->eof_reached()) { return OK; //all good } ERR_FAIL_COND_V(chunk_type != 0x004E4942, ERR_PARSE_ERROR); //BIN - state->glb_data.resize(chunk_length); - len = f->get_buffer(state->glb_data.ptrw(), chunk_length); + p_state->glb_data.resize(chunk_length); + len = p_file->get_buffer(p_state->glb_data.ptrw(), chunk_length); ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT); return OK; @@ -405,11 +394,11 @@ static Vector<real_t> _xform_to_array(const Transform3D p_transform) { return array; } -Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) { +Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) { Array nodes; - for (int i = 0; i < state->nodes.size(); i++) { + for (int i = 0; i < p_state->nodes.size(); i++) { Dictionary node; - Ref<GLTFNode> gltf_node = state->nodes[i]; + Ref<GLTFNode> gltf_node = p_state->nodes[i]; Dictionary extensions; node["extensions"] = extensions; if (!gltf_node->get_name().is_empty()) { @@ -454,21 +443,20 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) { node["children"] = children; } - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); - ERR_CONTINUE(!state->scene_nodes.find(i)); - Error err = ext->export_node(state, gltf_node, node, state->scene_nodes[i]); + ERR_CONTINUE(!p_state->scene_nodes.find(i)); + Error err = ext->export_node(p_state, gltf_node, node, p_state->scene_nodes[i]); ERR_CONTINUE(err != OK); } nodes.push_back(node); } - state->json["nodes"] = nodes; + p_state->json["nodes"] = nodes; return OK; } -String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name) { +String GLTFDocument::_gen_unique_name(Ref<GLTFState> p_state, const String &p_name) { const String s_name = p_name.validate_node_name(); String u_name; @@ -479,13 +467,13 @@ String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name if (index > 1) { u_name += itos(index); } - if (!state->unique_names.has(u_name)) { + if (!p_state->unique_names.has(u_name)) { break; } index++; } - state->unique_names.insert(u_name); + p_state->unique_names.insert(u_name); return u_name; } @@ -501,7 +489,7 @@ String GLTFDocument::_sanitize_animation_name(const String &p_name) { return anim_name; } -String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> state, const String &p_name) { +String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> p_state, const String &p_name) { const String s_name = _sanitize_animation_name(p_name); String u_name; @@ -512,13 +500,13 @@ String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> state, const Stri if (index > 1) { u_name += itos(index); } - if (!state->unique_animation_names.has(u_name)) { + if (!p_state->unique_animation_names.has(u_name)) { break; } index++; } - state->unique_animation_names.insert(u_name); + p_state->unique_animation_names.insert(u_name); return u_name; } @@ -530,7 +518,7 @@ String GLTFDocument::_sanitize_bone_name(const String &p_name) { return bone_name; } -String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i, const String &p_name) { +String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> p_state, const GLTFSkeletonIndex p_skel_i, const String &p_name) { String s_name = _sanitize_bone_name(p_name); if (s_name.is_empty()) { s_name = "bone"; @@ -543,23 +531,23 @@ String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkele if (index > 1) { u_name += "_" + itos(index); } - if (!state->skeletons[skel_i]->unique_names.has(u_name)) { + if (!p_state->skeletons[p_skel_i]->unique_names.has(u_name)) { break; } index++; } - state->skeletons.write[skel_i]->unique_names.insert(u_name); + p_state->skeletons.write[p_skel_i]->unique_names.insert(u_name); return u_name; } -Error GLTFDocument::_parse_scenes(Ref<GLTFState> state) { - ERR_FAIL_COND_V(!state->json.has("scenes"), ERR_FILE_CORRUPT); - const Array &scenes = state->json["scenes"]; +Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) { + ERR_FAIL_COND_V(!p_state->json.has("scenes"), ERR_FILE_CORRUPT); + const Array &scenes = p_state->json["scenes"]; int loaded_scene = 0; - if (state->json.has("scene")) { - loaded_scene = state->json["scene"]; + if (p_state->json.has("scene")) { + loaded_scene = p_state->json["scene"]; } else { WARN_PRINT("The load-time scene is not defined in the glTF2 file. Picking the first scene."); } @@ -570,22 +558,22 @@ Error GLTFDocument::_parse_scenes(Ref<GLTFState> state) { ERR_FAIL_COND_V(!s.has("nodes"), ERR_UNAVAILABLE); const Array &nodes = s["nodes"]; for (int j = 0; j < nodes.size(); j++) { - state->root_nodes.push_back(nodes[j]); + p_state->root_nodes.push_back(nodes[j]); } if (s.has("name") && !String(s["name"]).is_empty() && !((String)s["name"]).begins_with("Scene")) { - state->scene_name = _gen_unique_name(state, s["name"]); + p_state->scene_name = _gen_unique_name(p_state, s["name"]); } else { - state->scene_name = _gen_unique_name(state, state->filename); + p_state->scene_name = _gen_unique_name(p_state, p_state->filename); } } return OK; } -Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) { - ERR_FAIL_COND_V(!state->json.has("nodes"), ERR_FILE_CORRUPT); - const Array &nodes = state->json["nodes"]; +Error GLTFDocument::_parse_nodes(Ref<GLTFState> p_state) { + ERR_FAIL_COND_V(!p_state->json.has("nodes"), ERR_FILE_CORRUPT); + const Array &nodes = p_state->json["nodes"]; for (int i = 0; i < nodes.size(); i++) { Ref<GLTFNode> node; node.instantiate(); @@ -629,6 +617,11 @@ Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) { node->light = light; } } + for (Ref<GLTFDocumentExtension> ext : document_extensions) { + ERR_CONTINUE(ext.is_null()); + Error err = ext->parse_node_extensions(p_state, node, extensions); + ERR_CONTINUE_MSG(err != OK, "GLTF: Encountered error " + itos(err) + " when parsing node extensions for node " + node->get_name() + " in file " + p_state->filename + ". Continuing."); + } } if (n.has("children")) { @@ -638,35 +631,35 @@ Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) { } } - state->nodes.push_back(node); + p_state->nodes.push_back(node); } // build the hierarchy - for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { - for (int j = 0; j < state->nodes[node_i]->children.size(); j++) { - GLTFNodeIndex child_i = state->nodes[node_i]->children[j]; + for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) { + for (int j = 0; j < p_state->nodes[node_i]->children.size(); j++) { + GLTFNodeIndex child_i = p_state->nodes[node_i]->children[j]; - ERR_FAIL_INDEX_V(child_i, state->nodes.size(), ERR_FILE_CORRUPT); - ERR_CONTINUE(state->nodes[child_i]->parent != -1); //node already has a parent, wtf. + ERR_FAIL_INDEX_V(child_i, p_state->nodes.size(), ERR_FILE_CORRUPT); + ERR_CONTINUE(p_state->nodes[child_i]->parent != -1); //node already has a parent, wtf. - state->nodes.write[child_i]->parent = node_i; + p_state->nodes.write[child_i]->parent = node_i; } } - _compute_node_heights(state); + _compute_node_heights(p_state); return OK; } -void GLTFDocument::_compute_node_heights(Ref<GLTFState> state) { - state->root_nodes.clear(); - for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); ++node_i) { - Ref<GLTFNode> node = state->nodes[node_i]; +void GLTFDocument::_compute_node_heights(Ref<GLTFState> p_state) { + p_state->root_nodes.clear(); + for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); ++node_i) { + Ref<GLTFNode> node = p_state->nodes[node_i]; node->height = 0; GLTFNodeIndex current_i = node_i; while (current_i >= 0) { - const GLTFNodeIndex parent_i = state->nodes[current_i]->parent; + const GLTFNodeIndex parent_i = p_state->nodes[current_i]->parent; if (parent_i >= 0) { ++node->height; } @@ -674,7 +667,7 @@ void GLTFDocument::_compute_node_heights(Ref<GLTFState> state) { } if (node->height == 0) { - state->root_nodes.push_back(node_i); + p_state->root_nodes.push_back(node_i); } } } @@ -697,86 +690,86 @@ static Vector<uint8_t> _parse_base64_uri(const String &uri) { return buf; } -Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_path) { - print_verbose("glTF: Total buffers: " + itos(state->buffers.size())); +Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> p_state, const String &p_path) { + print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size())); - if (!state->buffers.size()) { + if (!p_state->buffers.size()) { return OK; } Array buffers; - if (state->buffers.size()) { - Vector<uint8_t> buffer_data = state->buffers[0]; + if (p_state->buffers.size()) { + Vector<uint8_t> buffer_data = p_state->buffers[0]; Dictionary gltf_buffer; gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); } - for (GLTFBufferIndex i = 1; i < state->buffers.size() - 1; i++) { - Vector<uint8_t> buffer_data = state->buffers[i]; + for (GLTFBufferIndex i = 1; i < p_state->buffers.size() - 1; i++) { + Vector<uint8_t> buffer_data = p_state->buffers[i]; Dictionary gltf_buffer; String filename = p_path.get_basename().get_file() + itos(i) + ".bin"; String path = p_path.get_base_dir() + "/" + filename; Error err; - Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err); - if (f.is_null()) { + Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &err); + if (file.is_null()) { return err; } if (buffer_data.size() == 0) { return OK; } - f->create(FileAccess::ACCESS_RESOURCES); - f->store_buffer(buffer_data.ptr(), buffer_data.size()); + file->create(FileAccess::ACCESS_RESOURCES); + file->store_buffer(buffer_data.ptr(), buffer_data.size()); gltf_buffer["uri"] = filename; gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); } - state->json["buffers"] = buffers; + p_state->json["buffers"] = buffers; return OK; } -Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_path) { - print_verbose("glTF: Total buffers: " + itos(state->buffers.size())); +Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> p_state, const String &p_path) { + print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size())); - if (!state->buffers.size()) { + if (!p_state->buffers.size()) { return OK; } Array buffers; - for (GLTFBufferIndex i = 0; i < state->buffers.size(); i++) { - Vector<uint8_t> buffer_data = state->buffers[i]; + for (GLTFBufferIndex i = 0; i < p_state->buffers.size(); i++) { + Vector<uint8_t> buffer_data = p_state->buffers[i]; Dictionary gltf_buffer; String filename = p_path.get_basename().get_file() + itos(i) + ".bin"; String path = p_path.get_base_dir() + "/" + filename; Error err; - Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err); - if (f.is_null()) { + Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &err); + if (file.is_null()) { return err; } if (buffer_data.size() == 0) { return OK; } - f->create(FileAccess::ACCESS_RESOURCES); - f->store_buffer(buffer_data.ptr(), buffer_data.size()); + file->create(FileAccess::ACCESS_RESOURCES); + file->store_buffer(buffer_data.ptr(), buffer_data.size()); gltf_buffer["uri"] = filename; gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); } - state->json["buffers"] = buffers; + p_state->json["buffers"] = buffers; return OK; } -Error GLTFDocument::_parse_buffers(Ref<GLTFState> state, const String &p_base_path) { - if (!state->json.has("buffers")) { +Error GLTFDocument::_parse_buffers(Ref<GLTFState> p_state, const String &p_base_path) { + if (!p_state->json.has("buffers")) { return OK; } - const Array &buffers = state->json["buffers"]; + const Array &buffers = p_state->json["buffers"]; for (GLTFBufferIndex i = 0; i < buffers.size(); i++) { - if (i == 0 && state->glb_data.size()) { - state->buffers.push_back(state->glb_data); + if (i == 0 && p_state->glb_data.size()) { + p_state->buffers.push_back(p_state->glb_data); } else { const Dictionary &buffer = buffers[i]; @@ -795,29 +788,29 @@ Error GLTFDocument::_parse_buffers(Ref<GLTFState> state, const String &p_base_pa ERR_FAIL_COND_V(p_base_path.is_empty(), ERR_INVALID_PARAMETER); uri = uri.uri_decode(); uri = p_base_path.path_join(uri).replace("\\", "/"); // Fix for Windows. - buffer_data = FileAccess::get_file_as_array(uri); + buffer_data = FileAccess::get_file_as_bytes(uri); ERR_FAIL_COND_V_MSG(buffer.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load binary file as an array: " + uri); } ERR_FAIL_COND_V(!buffer.has("byteLength"), ERR_PARSE_ERROR); int byteLength = buffer["byteLength"]; ERR_FAIL_COND_V(byteLength < buffer_data.size(), ERR_PARSE_ERROR); - state->buffers.push_back(buffer_data); + p_state->buffers.push_back(buffer_data); } } } - print_verbose("glTF: Total buffers: " + itos(state->buffers.size())); + print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size())); return OK; } -Error GLTFDocument::_encode_buffer_views(Ref<GLTFState> state) { +Error GLTFDocument::_encode_buffer_views(Ref<GLTFState> p_state) { Array buffers; - for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) { + for (GLTFBufferViewIndex i = 0; i < p_state->buffer_views.size(); i++) { Dictionary d; - Ref<GLTFBufferView> buffer_view = state->buffer_views[i]; + Ref<GLTFBufferView> buffer_view = p_state->buffer_views[i]; d["buffer"] = buffer_view->buffer; d["byteLength"] = buffer_view->byte_length; @@ -835,19 +828,19 @@ Error GLTFDocument::_encode_buffer_views(Ref<GLTFState> state) { ERR_FAIL_COND_V(!d.has("byteLength"), ERR_INVALID_DATA); buffers.push_back(d); } - print_verbose("glTF: Total buffer views: " + itos(state->buffer_views.size())); + print_verbose("glTF: Total buffer views: " + itos(p_state->buffer_views.size())); if (!buffers.size()) { return OK; } - state->json["bufferViews"] = buffers; + p_state->json["bufferViews"] = buffers; return OK; } -Error GLTFDocument::_parse_buffer_views(Ref<GLTFState> state) { - if (!state->json.has("bufferViews")) { +Error GLTFDocument::_parse_buffer_views(Ref<GLTFState> p_state) { + if (!p_state->json.has("bufferViews")) { return OK; } - const Array &buffers = state->json["bufferViews"]; + const Array &buffers = p_state->json["bufferViews"]; for (GLTFBufferViewIndex i = 0; i < buffers.size(); i++) { const Dictionary &d = buffers[i]; @@ -872,20 +865,20 @@ Error GLTFDocument::_parse_buffer_views(Ref<GLTFState> state) { buffer_view->indices = target == GLTFDocument::ELEMENT_ARRAY_BUFFER; } - state->buffer_views.push_back(buffer_view); + p_state->buffer_views.push_back(buffer_view); } - print_verbose("glTF: Total buffer views: " + itos(state->buffer_views.size())); + print_verbose("glTF: Total buffer views: " + itos(p_state->buffer_views.size())); return OK; } -Error GLTFDocument::_encode_accessors(Ref<GLTFState> state) { +Error GLTFDocument::_encode_accessors(Ref<GLTFState> p_state) { Array accessors; - for (GLTFAccessorIndex i = 0; i < state->accessors.size(); i++) { + for (GLTFAccessorIndex i = 0; i < p_state->accessors.size(); i++) { Dictionary d; - Ref<GLTFAccessor> accessor = state->accessors[i]; + Ref<GLTFAccessor> accessor = p_state->accessors[i]; d["componentType"] = accessor->component_type; d["count"] = accessor->count; d["type"] = _get_accessor_type_name(accessor->type); @@ -931,9 +924,9 @@ Error GLTFDocument::_encode_accessors(Ref<GLTFState> state) { if (!accessors.size()) { return OK; } - state->json["accessors"] = accessors; - ERR_FAIL_COND_V(!state->json.has("accessors"), ERR_FILE_CORRUPT); - print_verbose("glTF: Total accessors: " + itos(state->accessors.size())); + p_state->json["accessors"] = accessors; + ERR_FAIL_COND_V(!p_state->json.has("accessors"), ERR_FILE_CORRUPT); + print_verbose("glTF: Total accessors: " + itos(p_state->accessors.size())); return OK; } @@ -992,11 +985,11 @@ GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { ERR_FAIL_V(GLTFType::TYPE_SCALAR); } -Error GLTFDocument::_parse_accessors(Ref<GLTFState> state) { - if (!state->json.has("accessors")) { +Error GLTFDocument::_parse_accessors(Ref<GLTFState> p_state) { + if (!p_state->json.has("accessors")) { return OK; } - const Array &accessors = state->json["accessors"]; + const Array &accessors = p_state->json["accessors"]; for (GLTFAccessorIndex i = 0; i < accessors.size(); i++) { const Dictionary &d = accessors[i]; @@ -1059,10 +1052,10 @@ Error GLTFDocument::_parse_accessors(Ref<GLTFState> state) { } } - state->accessors.push_back(accessor); + p_state->accessors.push_back(accessor); } - print_verbose("glTF: Total accessors: " + itos(state->accessors.size())); + print_verbose("glTF: Total accessors: " + itos(p_state->accessors.size())); return OK; } @@ -1107,33 +1100,33 @@ String GLTFDocument::_get_type_name(const GLTFType p_component) { return names[p_component]; } -Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, const int count, const GLTFType type, const int component_type, const bool normalized, const int byte_offset, const bool for_vertex, GLTFBufferViewIndex &r_accessor) { +Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_src, const int p_count, const GLTFType p_type, const int p_component_type, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex, GLTFBufferViewIndex &r_accessor) { const int component_count_for_type[7] = { 1, 2, 3, 4, 4, 9, 16 }; - const int component_count = component_count_for_type[type]; - const int component_size = _get_component_type_size(component_type); + const int component_count = component_count_for_type[p_type]; + const int component_size = _get_component_type_size(p_component_type); ERR_FAIL_COND_V(component_size == 0, FAILED); int skip_every = 0; int skip_bytes = 0; //special case of alignments, as described in spec - switch (component_type) { + switch (p_component_type) { case COMPONENT_TYPE_BYTE: case COMPONENT_TYPE_UNSIGNED_BYTE: { - if (type == TYPE_MAT2) { + if (p_type == TYPE_MAT2) { skip_every = 2; skip_bytes = 2; } - if (type == TYPE_MAT3) { + if (p_type == TYPE_MAT3) { skip_every = 3; skip_bytes = 1; } } break; case COMPONENT_TYPE_SHORT: case COMPONENT_TYPE_UNSIGNED_SHORT: { - if (type == TYPE_MAT3) { + if (p_type == TYPE_MAT3) { skip_every = 6; skip_bytes = 4; } @@ -1144,39 +1137,39 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, Ref<GLTFBufferView> bv; bv.instantiate(); - const uint32_t offset = bv->byte_offset = byte_offset; - Vector<uint8_t> &gltf_buffer = state->buffers.write[0]; + const uint32_t offset = bv->byte_offset = p_byte_offset; + Vector<uint8_t> &gltf_buffer = p_state->buffers.write[0]; - int stride = _get_component_type_size(component_type); - if (for_vertex && stride % 4) { + int stride = _get_component_type_size(p_component_type); + if (p_for_vertex && stride % 4) { stride += 4 - (stride % 4); //according to spec must be multiple of 4 } //use to debug - print_verbose("glTF: encoding type " + _get_type_name(type) + " component type: " + _get_component_type_name(component_type) + " stride: " + itos(stride) + " amount " + itos(count)); + print_verbose("glTF: encoding type " + _get_type_name(p_type) + " component type: " + _get_component_type_name(p_component_type) + " stride: " + itos(stride) + " amount " + itos(p_count)); - print_verbose("glTF: encoding accessor offset " + itos(byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(gltf_buffer.size()) + " view len " + itos(bv->byte_length)); + print_verbose("glTF: encoding accessor offset " + itos(p_byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(gltf_buffer.size()) + " view len " + itos(bv->byte_length)); - const int buffer_end = (stride * (count - 1)) + _get_component_type_size(component_type); + const int buffer_end = (stride * (p_count - 1)) + _get_component_type_size(p_component_type); // TODO define bv->byte_stride bv->byte_offset = gltf_buffer.size(); - switch (component_type) { + switch (p_component_type) { case COMPONENT_TYPE_BYTE: { Vector<int8_t> buffer; - buffer.resize(count * component_count); + buffer.resize(p_count * component_count); int32_t dst_i = 0; - for (int i = 0; i < count; i++) { + for (int i = 0; i < p_count; i++) { for (int j = 0; j < component_count; j++) { if (skip_every && j > 0 && (j % skip_every) == 0) { dst_i += skip_bytes; } - double d = *src; - if (normalized) { + double d = *p_src; + if (p_normalized) { buffer.write[dst_i] = d * 128.0; } else { buffer.write[dst_i] = d; } - src++; + p_src++; dst_i++; } } @@ -1187,20 +1180,20 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, } break; case COMPONENT_TYPE_UNSIGNED_BYTE: { Vector<uint8_t> buffer; - buffer.resize(count * component_count); + buffer.resize(p_count * component_count); int32_t dst_i = 0; - for (int i = 0; i < count; i++) { + for (int i = 0; i < p_count; i++) { for (int j = 0; j < component_count; j++) { if (skip_every && j > 0 && (j % skip_every) == 0) { dst_i += skip_bytes; } - double d = *src; - if (normalized) { + double d = *p_src; + if (p_normalized) { buffer.write[dst_i] = d * 255.0; } else { buffer.write[dst_i] = d; } - src++; + p_src++; dst_i++; } } @@ -1209,20 +1202,20 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, } break; case COMPONENT_TYPE_SHORT: { Vector<int16_t> buffer; - buffer.resize(count * component_count); + buffer.resize(p_count * component_count); int32_t dst_i = 0; - for (int i = 0; i < count; i++) { + for (int i = 0; i < p_count; i++) { for (int j = 0; j < component_count; j++) { if (skip_every && j > 0 && (j % skip_every) == 0) { dst_i += skip_bytes; } - double d = *src; - if (normalized) { + double d = *p_src; + if (p_normalized) { buffer.write[dst_i] = d * 32768.0; } else { buffer.write[dst_i] = d; } - src++; + p_src++; dst_i++; } } @@ -1233,20 +1226,20 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, } break; case COMPONENT_TYPE_UNSIGNED_SHORT: { Vector<uint16_t> buffer; - buffer.resize(count * component_count); + buffer.resize(p_count * component_count); int32_t dst_i = 0; - for (int i = 0; i < count; i++) { + for (int i = 0; i < p_count; i++) { for (int j = 0; j < component_count; j++) { if (skip_every && j > 0 && (j % skip_every) == 0) { dst_i += skip_bytes; } - double d = *src; - if (normalized) { + double d = *p_src; + if (p_normalized) { buffer.write[dst_i] = d * 65535.0; } else { buffer.write[dst_i] = d; } - src++; + p_src++; dst_i++; } } @@ -1257,16 +1250,16 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, } break; case COMPONENT_TYPE_INT: { Vector<int> buffer; - buffer.resize(count * component_count); + buffer.resize(p_count * component_count); int32_t dst_i = 0; - for (int i = 0; i < count; i++) { + for (int i = 0; i < p_count; i++) { for (int j = 0; j < component_count; j++) { if (skip_every && j > 0 && (j % skip_every) == 0) { dst_i += skip_bytes; } - double d = *src; + double d = *p_src; buffer.write[dst_i] = d; - src++; + p_src++; dst_i++; } } @@ -1277,16 +1270,16 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, } break; case COMPONENT_TYPE_FLOAT: { Vector<float> buffer; - buffer.resize(count * component_count); + buffer.resize(p_count * component_count); int32_t dst_i = 0; - for (int i = 0; i < count; i++) { + for (int i = 0; i < p_count; i++) { for (int j = 0; j < component_count; j++) { if (skip_every && j > 0 && (j % skip_every) == 0) { dst_i += skip_bytes; } - double d = *src; + double d = *p_src; buffer.write[dst_i] = d; - src++; + p_src++; dst_i++; } } @@ -1299,53 +1292,53 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_INVALID_DATA); ERR_FAIL_COND_V((int)(offset + buffer_end) > gltf_buffer.size(), ERR_INVALID_DATA); - r_accessor = bv->buffer = state->buffer_views.size(); - state->buffer_views.push_back(bv); + r_accessor = bv->buffer = p_state->buffer_views.size(); + p_state->buffer_views.push_back(bv); return OK; } -Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const GLTFBufferViewIndex p_buffer_view, const int skip_every, const int skip_bytes, const int element_size, const int count, const GLTFType type, const int component_count, const int component_type, const int component_size, const bool normalized, const int byte_offset, const bool for_vertex) { - const Ref<GLTFBufferView> bv = state->buffer_views[p_buffer_view]; +Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, const GLTFBufferViewIndex p_buffer_view, const int p_skip_every, const int p_skip_bytes, const int p_element_size, const int p_count, const GLTFType p_type, const int p_component_count, const int p_component_type, const int p_component_size, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex) { + const Ref<GLTFBufferView> bv = p_state->buffer_views[p_buffer_view]; - int stride = element_size; + int stride = p_element_size; if (bv->byte_stride != -1) { stride = bv->byte_stride; } - if (for_vertex && stride % 4) { + if (p_for_vertex && stride % 4) { stride += 4 - (stride % 4); //according to spec must be multiple of 4 } - ERR_FAIL_INDEX_V(bv->buffer, state->buffers.size(), ERR_PARSE_ERROR); + ERR_FAIL_INDEX_V(bv->buffer, p_state->buffers.size(), ERR_PARSE_ERROR); - const uint32_t offset = bv->byte_offset + byte_offset; - Vector<uint8_t> buffer = state->buffers[bv->buffer]; //copy on write, so no performance hit + const uint32_t offset = bv->byte_offset + p_byte_offset; + Vector<uint8_t> buffer = p_state->buffers[bv->buffer]; //copy on write, so no performance hit const uint8_t *bufptr = buffer.ptr(); //use to debug - print_verbose("glTF: type " + _get_type_name(type) + " component type: " + _get_component_type_name(component_type) + " stride: " + itos(stride) + " amount " + itos(count)); - print_verbose("glTF: accessor offset " + itos(byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(buffer.size()) + " view len " + itos(bv->byte_length)); + print_verbose("glTF: type " + _get_type_name(p_type) + " component type: " + _get_component_type_name(p_component_type) + " stride: " + itos(stride) + " amount " + itos(p_count)); + print_verbose("glTF: accessor offset " + itos(p_byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(buffer.size()) + " view len " + itos(bv->byte_length)); - const int buffer_end = (stride * (count - 1)) + element_size; + const int buffer_end = (stride * (p_count - 1)) + p_element_size; ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_PARSE_ERROR); ERR_FAIL_COND_V((int)(offset + buffer_end) > buffer.size(), ERR_PARSE_ERROR); //fill everything as doubles - for (int i = 0; i < count; i++) { + for (int i = 0; i < p_count; i++) { const uint8_t *src = &bufptr[offset + i * stride]; - for (int j = 0; j < component_count; j++) { - if (skip_every && j > 0 && (j % skip_every) == 0) { - src += skip_bytes; + for (int j = 0; j < p_component_count; j++) { + if (p_skip_every && j > 0 && (j % p_skip_every) == 0) { + src += p_skip_bytes; } double d = 0; - switch (component_type) { + switch (p_component_type) { case COMPONENT_TYPE_BYTE: { int8_t b = int8_t(*src); - if (normalized) { + if (p_normalized) { d = (double(b) / 128.0); } else { d = double(b); @@ -1353,7 +1346,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const } break; case COMPONENT_TYPE_UNSIGNED_BYTE: { uint8_t b = *src; - if (normalized) { + if (p_normalized) { d = (double(b) / 255.0); } else { d = double(b); @@ -1361,7 +1354,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const } break; case COMPONENT_TYPE_SHORT: { int16_t s = *(int16_t *)src; - if (normalized) { + if (p_normalized) { d = (double(s) / 32768.0); } else { d = double(s); @@ -1369,7 +1362,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const } break; case COMPONENT_TYPE_UNSIGNED_SHORT: { uint16_t s = *(uint16_t *)src; - if (normalized) { + if (p_normalized) { d = (double(s) / 65535.0); } else { d = double(s); @@ -1383,16 +1376,16 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const } break; } - *dst++ = d; - src += component_size; + *p_dst++ = d; + src += p_component_size; } } return OK; } -int GLTFDocument::_get_component_type_size(const int component_type) { - switch (component_type) { +int GLTFDocument::_get_component_type_size(const int p_component_type) { + switch (p_component_type) { case COMPONENT_TYPE_BYTE: case COMPONENT_TYPE_UNSIGNED_BYTE: return 1; @@ -1412,13 +1405,13 @@ int GLTFDocument::_get_component_type_size(const int component_type) { return 0; } -Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { +Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { //spec, for reference: //https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment - ERR_FAIL_INDEX_V(p_accessor, state->accessors.size(), Vector<double>()); + ERR_FAIL_INDEX_V(p_accessor, p_state->accessors.size(), Vector<double>()); - const Ref<GLTFAccessor> a = state->accessors[p_accessor]; + const Ref<GLTFAccessor> a = p_state->accessors[p_accessor]; const int component_count_for_type[7] = { 1, 2, 3, 4, 4, 9, 16 @@ -1463,9 +1456,9 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAc double *dst = dst_buffer.ptrw(); if (a->buffer_view >= 0) { - ERR_FAIL_INDEX_V(a->buffer_view, state->buffer_views.size(), Vector<double>()); + ERR_FAIL_INDEX_V(a->buffer_view, p_state->buffer_views.size(), Vector<double>()); - const Error err = _decode_buffer_view(state, dst, a->buffer_view, skip_every, skip_bytes, element_size, a->count, a->type, component_count, a->component_type, component_size, a->normalized, a->byte_offset, p_for_vertex); + const Error err = _decode_buffer_view(p_state, dst, a->buffer_view, skip_every, skip_bytes, element_size, a->count, a->type, component_count, a->component_type, component_size, a->normalized, a->byte_offset, p_for_vertex); if (err != OK) { return Vector<double>(); } @@ -1482,14 +1475,14 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAc indices.resize(a->sparse_count); const int indices_component_size = _get_component_type_size(a->sparse_indices_component_type); - Error err = _decode_buffer_view(state, indices.ptrw(), a->sparse_indices_buffer_view, 0, 0, indices_component_size, a->sparse_count, TYPE_SCALAR, 1, a->sparse_indices_component_type, indices_component_size, false, a->sparse_indices_byte_offset, false); + Error err = _decode_buffer_view(p_state, indices.ptrw(), a->sparse_indices_buffer_view, 0, 0, indices_component_size, a->sparse_count, TYPE_SCALAR, 1, a->sparse_indices_component_type, indices_component_size, false, a->sparse_indices_byte_offset, false); if (err != OK) { return Vector<double>(); } Vector<double> data; data.resize(component_count * a->sparse_count); - err = _decode_buffer_view(state, data.ptrw(), a->sparse_values_buffer_view, skip_every, skip_bytes, element_size, a->sparse_count, a->type, component_count, a->component_type, component_size, a->normalized, a->sparse_values_byte_offset, p_for_vertex); + err = _decode_buffer_view(p_state, data.ptrw(), a->sparse_values_buffer_view, skip_every, skip_bytes, element_size, a->sparse_count, a->type, component_count, a->component_type, component_size, a->normalized, a->sparse_values_byte_offset, p_for_vertex); if (err != OK) { return Vector<double>(); } @@ -1506,7 +1499,7 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAc return dst_buffer; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, const Vector<int32_t> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> p_state, const Vector<int32_t> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1539,7 +1532,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, c Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_SCALAR; const int component_type = GLTFDocument::COMPONENT_TYPE_INT; @@ -1550,17 +1543,17 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, c accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<int> ret; if (attribs.size() == 0) { @@ -1578,8 +1571,8 @@ Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> state, const G return ret; } -Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<float> ret; if (attribs.size() == 0) { @@ -1597,7 +1590,7 @@ Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> state, con return ret; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, const Vector<Vector2> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> p_state, const Vector<Vector2> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1623,7 +1616,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, c Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_VEC2; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; @@ -1634,16 +1627,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, c accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1672,7 +1665,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state, Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; @@ -1683,31 +1676,31 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state, accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -void GLTFDocument::_calc_accessor_min_max(int i, const int element_count, Vector<double> &type_max, Vector<double> attribs, Vector<double> &type_min) { - if (i == 0) { - for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.write[type_i] = attribs[(i * element_count) + type_i]; - type_min.write[type_i] = attribs[(i * element_count) + type_i]; +void GLTFDocument::_calc_accessor_min_max(int p_i, const int p_element_count, Vector<double> &p_type_max, Vector<double> p_attribs, Vector<double> &p_type_min) { + if (p_i == 0) { + for (int32_t type_i = 0; type_i < p_element_count; type_i++) { + p_type_max.write[type_i] = p_attribs[(p_i * p_element_count) + type_i]; + p_type_min.write[type_i] = p_attribs[(p_i * p_element_count) + type_i]; } } - for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.write[type_i] = MAX(attribs[(i * element_count) + type_i], type_max[type_i]); - type_min.write[type_i] = MIN(attribs[(i * element_count) + type_i], type_min[type_i]); - type_max.write[type_i] = _filter_number(type_max.write[type_i]); - type_min.write[type_i] = _filter_number(type_min.write[type_i]); + for (int32_t type_i = 0; type_i < p_element_count; type_i++) { + p_type_max.write[type_i] = MAX(p_attribs[(p_i * p_element_count) + type_i], p_type_max[type_i]); + p_type_min.write[type_i] = MIN(p_attribs[(p_i * p_element_count) + type_i], p_type_min[type_i]); + p_type_max.write[type_i] = _filter_number(p_type_max.write[type_i]); + p_type_min.write[type_i] = _filter_number(p_type_min.write[type_i]); } } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1737,7 +1730,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; @@ -1748,16 +1741,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1784,7 +1777,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state, Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT; @@ -1795,16 +1788,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state, accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> state, const Vector<Quaternion> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> p_state, const Vector<Quaternion> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1833,7 +1826,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> s Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; @@ -1844,17 +1837,17 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> s accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<Vector2> ret; if (attribs.size() == 0) { @@ -1873,7 +1866,7 @@ Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> state, con return ret; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state, const Vector<real_t> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> p_state, const Vector<real_t> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1898,7 +1891,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state, Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_SCALAR; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; @@ -1909,16 +1902,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state, accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, const Vector<Vector3> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> p_state, const Vector<Vector3> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1944,7 +1937,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, c Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_VEC3; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; @@ -1955,16 +1948,16 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, c accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state, const Vector<Transform3D> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> p_state, const Vector<Transform3D> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -2012,7 +2005,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state, Ref<GLTFAccessor> accessor; accessor.instantiate(); GLTFBufferIndex buffer_view_i; - int64_t size = state->buffers[0].size(); + int64_t size = p_state->buffers[0].size(); const GLTFType type = GLTFType::TYPE_MAT4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; @@ -2023,17 +2016,17 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state, accessor->type = type; accessor->component_type = component_type; accessor->byte_offset = 0; - Error err = _encode_buffer_view(state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); + Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i); if (err != OK) { return -1; } accessor->buffer_view = buffer_view_i; - state->accessors.push_back(accessor); - return state->accessors.size() - 1; + p_state->accessors.push_back(accessor); + return p_state->accessors.size() - 1; } -Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<Vector3> ret; if (attribs.size() == 0) { @@ -2052,15 +2045,15 @@ Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> state, con return ret; } -Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<Color> ret; if (attribs.size() == 0) { return ret; } - const int type = state->accessors[p_accessor]->type; + const int type = p_state->accessors[p_accessor]->type; ERR_FAIL_COND_V(!(type == TYPE_VEC3 || type == TYPE_VEC4), ret); int vec_len = 3; if (type == TYPE_VEC4) { @@ -2078,8 +2071,8 @@ Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> state, cons } return ret; } -Vector<Quaternion> GLTFDocument::_decode_accessor_as_quaternion(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<Quaternion> GLTFDocument::_decode_accessor_as_quaternion(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<Quaternion> ret; if (attribs.size() == 0) { @@ -2097,8 +2090,8 @@ Vector<Quaternion> GLTFDocument::_decode_accessor_as_quaternion(Ref<GLTFState> s } return ret; } -Vector<Transform2D> GLTFDocument::_decode_accessor_as_xform2d(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<Transform2D> GLTFDocument::_decode_accessor_as_xform2d(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<Transform2D> ret; if (attribs.size() == 0) { @@ -2114,8 +2107,8 @@ Vector<Transform2D> GLTFDocument::_decode_accessor_as_xform2d(Ref<GLTFState> sta return ret; } -Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<Basis> ret; if (attribs.size() == 0) { @@ -2132,8 +2125,8 @@ Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> state, cons return ret; } -Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); +Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); Vector<Transform3D> ret; if (attribs.size() == 0) { @@ -2151,15 +2144,15 @@ Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> state return ret; } -Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { +Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) { Array meshes; - for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < state->meshes.size(); gltf_mesh_i++) { + for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < p_state->meshes.size(); gltf_mesh_i++) { print_verbose("glTF: Serializing mesh: " + itos(gltf_mesh_i)); - Ref<ImporterMesh> import_mesh = state->meshes.write[gltf_mesh_i]->get_mesh(); + Ref<ImporterMesh> import_mesh = p_state->meshes.write[gltf_mesh_i]->get_mesh(); if (import_mesh.is_null()) { continue; } - Array instance_materials = state->meshes.write[gltf_mesh_i]->get_instance_materials(); + Array instance_materials = p_state->meshes.write[gltf_mesh_i]->get_instance_materials(); Array primitives; Dictionary gltf_mesh; Array target_names; @@ -2212,7 +2205,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { { Vector<Vector3> a = array[Mesh::ARRAY_VERTEX]; ERR_FAIL_COND_V(!a.size(), ERR_INVALID_DATA); - attributes["POSITION"] = _encode_accessor_as_vec3(state, a, true); + attributes["POSITION"] = _encode_accessor_as_vec3(p_state, a, true); vertex_num = a.size(); } { @@ -2229,7 +2222,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { out.a = a[(i * 4) + 3]; attribs.write[i] = out; } - attributes["TANGENT"] = _encode_accessor_as_color(state, attribs, true); + attributes["TANGENT"] = _encode_accessor_as_color(p_state, attribs, true); } } { @@ -2241,19 +2234,19 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { for (int i = 0; i < ret_size; i++) { attribs.write[i] = Vector3(a[i]).normalized(); } - attributes["NORMAL"] = _encode_accessor_as_vec3(state, attribs, true); + attributes["NORMAL"] = _encode_accessor_as_vec3(p_state, attribs, true); } } { Vector<Vector2> a = array[Mesh::ARRAY_TEX_UV]; if (a.size()) { - attributes["TEXCOORD_0"] = _encode_accessor_as_vec2(state, a, true); + attributes["TEXCOORD_0"] = _encode_accessor_as_vec2(p_state, a, true); } } { Vector<Vector2> a = array[Mesh::ARRAY_TEX_UV2]; if (a.size()) { - attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(state, a, true); + attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(p_state, a, true); } } for (int custom_i = 0; custom_i < 3; custom_i++) { @@ -2282,7 +2275,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { if (!attributes.has(gltf_texcoord_key)) { Vector<Vector2> empty; empty.resize(vertex_num); - attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, empty, true); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(p_state, empty, true); } } @@ -2303,25 +2296,25 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { } } gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i); - attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, first_channel, true); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(p_state, first_channel, true); gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1); - attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, second_channel, true); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(p_state, second_channel, true); } } { Vector<Color> a = array[Mesh::ARRAY_COLOR]; if (a.size()) { - attributes["COLOR_0"] = _encode_accessor_as_color(state, a, true); + attributes["COLOR_0"] = _encode_accessor_as_color(p_state, a, true); } } HashMap<int, int> joint_i_to_bone_i; - for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { + for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) { GLTFSkinIndex skin_i = -1; - if (state->nodes[node_i]->mesh == gltf_mesh_i) { - skin_i = state->nodes[node_i]->skin; + if (p_state->nodes[node_i]->mesh == gltf_mesh_i) { + skin_i = p_state->nodes[node_i]->skin; } if (skin_i != -1) { - joint_i_to_bone_i = state->skins[skin_i]->joint_i_to_bone_i; + joint_i_to_bone_i = p_state->skins[skin_i]->joint_i_to_bone_i; break; } } @@ -2341,7 +2334,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { attribs.write[array_i] = Color(joint_0, joint_1, joint_2, joint_3); } } - attributes["JOINTS_0"] = _encode_accessor_as_joints(state, attribs, true); + attributes["JOINTS_0"] = _encode_accessor_as_joints(p_state, attribs, true); } else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) { Vector<Color> joints_0; joints_0.resize(vertex_num); @@ -2362,8 +2355,8 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { joint_1.a = a[vertex_i * weights_8_count + 7]; joints_1.write[vertex_i] = joint_1; } - attributes["JOINTS_0"] = _encode_accessor_as_joints(state, joints_0, true); - attributes["JOINTS_1"] = _encode_accessor_as_joints(state, joints_1, true); + attributes["JOINTS_0"] = _encode_accessor_as_joints(p_state, joints_0, true); + attributes["JOINTS_1"] = _encode_accessor_as_joints(p_state, joints_1, true); } } { @@ -2376,7 +2369,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { for (int i = 0; i < vertex_count; i++) { attribs.write[i] = Color(a[(i * JOINT_GROUP_SIZE) + 0], a[(i * JOINT_GROUP_SIZE) + 1], a[(i * JOINT_GROUP_SIZE) + 2], a[(i * JOINT_GROUP_SIZE) + 3]); } - attributes["WEIGHTS_0"] = _encode_accessor_as_weights(state, attribs, true); + attributes["WEIGHTS_0"] = _encode_accessor_as_weights(p_state, attribs, true); } else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) { Vector<Color> weights_0; weights_0.resize(vertex_num); @@ -2397,8 +2390,8 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { weight_1.a = a[vertex_i * weights_8_count + 7]; weights_1.write[vertex_i] = weight_1; } - attributes["WEIGHTS_0"] = _encode_accessor_as_weights(state, weights_0, true); - attributes["WEIGHTS_1"] = _encode_accessor_as_weights(state, weights_1, true); + attributes["WEIGHTS_0"] = _encode_accessor_as_weights(p_state, weights_0, true); + attributes["WEIGHTS_1"] = _encode_accessor_as_weights(p_state, weights_1, true); } } { @@ -2411,7 +2404,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { SWAP(mesh_indices.write[k + 0], mesh_indices.write[k + 2]); } } - primitive["indices"] = _encode_accessor_as_ints(state, mesh_indices, true); + primitive["indices"] = _encode_accessor_as_ints(p_state, mesh_indices, true); } else { if (primitive_type == Mesh::PRIMITIVE_TRIANGLES) { //generate indices because they need to be swapped for CW/CCW @@ -2430,7 +2423,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { generated_indices.write[k + 2] = k + 1; } } - primitive["indices"] = _encode_accessor_as_ints(state, generated_indices, true); + primitive["indices"] = _encode_accessor_as_ints(p_state, generated_indices, true); } } } @@ -2455,12 +2448,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { } } - t["POSITION"] = _encode_accessor_as_vec3(state, varr, true); + t["POSITION"] = _encode_accessor_as_vec3(p_state, varr, true); } Vector<Vector3> narr = array_morph[Mesh::ARRAY_NORMAL]; if (narr.size()) { - t["NORMAL"] = _encode_accessor_as_vec3(state, narr, true); + t["NORMAL"] = _encode_accessor_as_vec3(p_state, narr, true); } Vector<real_t> tarr = array_morph[Mesh::ARRAY_TANGENT]; if (tarr.size()) { @@ -2473,7 +2466,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { vec3.y = tarr[(i * 4) + 1]; vec3.z = tarr[(i * 4) + 2]; } - t["TANGENT"] = _encode_accessor_as_vec3(state, attribs, true); + t["TANGENT"] = _encode_accessor_as_vec3(p_state, attribs, true); } targets.push_back(t); } @@ -2483,19 +2476,19 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { if (surface_i < instance_materials.size()) { v = instance_materials.get(surface_i); } - Ref<BaseMaterial3D> mat = v; + Ref<Material> mat = v; if (!mat.is_valid()) { mat = import_mesh->get_surface_material(surface_i); } if (mat.is_valid()) { - HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex>::Iterator material_cache_i = state->material_cache.find(mat); + HashMap<Ref<Material>, GLTFMaterialIndex>::Iterator material_cache_i = p_state->material_cache.find(mat); if (material_cache_i && material_cache_i->value != -1) { primitive["material"] = material_cache_i->value; } else { - GLTFMaterialIndex mat_i = state->materials.size(); - state->materials.push_back(mat); + GLTFMaterialIndex mat_i = p_state->materials.size(); + p_state->materials.push_back(mat); primitive["material"] = mat_i; - state->material_cache.insert(mat, mat_i); + p_state->material_cache.insert(mat, mat_i); } } @@ -2512,8 +2505,8 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { weights.resize(target_names.size()); for (int name_i = 0; name_i < target_names.size(); name_i++) { real_t weight = 0.0; - if (name_i < state->meshes.write[gltf_mesh_i]->get_blend_weights().size()) { - weight = state->meshes.write[gltf_mesh_i]->get_blend_weights()[name_i]; + if (name_i < p_state->meshes.write[gltf_mesh_i]->get_blend_weights().size()) { + weight = p_state->meshes.write[gltf_mesh_i]->get_blend_weights()[name_i]; } weights[name_i] = weight; } @@ -2533,18 +2526,18 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { if (!meshes.size()) { return OK; } - state->json["meshes"] = meshes; + p_state->json["meshes"] = meshes; print_verbose("glTF: Total meshes: " + itos(meshes.size())); return OK; } -Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { - if (!state->json.has("meshes")) { +Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { + if (!p_state->json.has("meshes")) { return OK; } - Array meshes = state->json["meshes"]; + Array meshes = p_state->json["meshes"]; for (GLTFMeshIndex i = 0; i < meshes.size(); i++) { print_verbose("glTF: Parsing mesh: " + itos(i)); Dictionary d = meshes[i]; @@ -2563,7 +2556,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { if (d.has("name") && !String(d["name"]).is_empty()) { mesh_name = d["name"]; } - import_mesh->set_name(_gen_unique_name(state, vformat("%s_%s", state->scene_name, mesh_name))); + import_mesh->set_name(_gen_unique_name(p_state, vformat("%s_%s", p_state->scene_name, mesh_name))); for (int j = 0; j < primitives.size(); j++) { uint32_t flags = 0; @@ -2599,21 +2592,21 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR); int32_t vertex_num = 0; if (a.has("POSITION")) { - PackedVector3Array vertices = _decode_accessor_as_vec3(state, a["POSITION"], true); + PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"], true); array[Mesh::ARRAY_VERTEX] = vertices; vertex_num = vertices.size(); } if (a.has("NORMAL")) { - array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true); + array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(p_state, a["NORMAL"], true); } if (a.has("TANGENT")) { - array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(state, a["TANGENT"], true); + array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(p_state, a["TANGENT"], true); } if (a.has("TEXCOORD_0")) { - array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(state, a["TEXCOORD_0"], true); + array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_0"], true); } if (a.has("TEXCOORD_1")) { - array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(state, a["TEXCOORD_1"], true); + array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_1"], true); } for (int custom_i = 0; custom_i < 3; custom_i++) { Vector<float> cur_custom; @@ -2624,12 +2617,12 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { String gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i); int num_channels = 0; if (a.has(gltf_texcoord_key)) { - texcoord_first = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true); + texcoord_first = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true); num_channels = 2; } gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1); if (a.has(gltf_texcoord_key)) { - texcoord_second = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true); + texcoord_second = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true); num_channels = 4; } if (!num_channels) { @@ -2670,14 +2663,14 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } } if (a.has("COLOR_0")) { - array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(state, a["COLOR_0"], true); + array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(p_state, a["COLOR_0"], true); has_vertex_color = true; } if (a.has("JOINTS_0") && !a.has("JOINTS_1")) { - array[Mesh::ARRAY_BONES] = _decode_accessor_as_ints(state, a["JOINTS_0"], true); + array[Mesh::ARRAY_BONES] = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true); } else if (a.has("JOINTS_0") && a.has("JOINTS_1")) { - PackedInt32Array joints_0 = _decode_accessor_as_ints(state, a["JOINTS_0"], true); - PackedInt32Array joints_1 = _decode_accessor_as_ints(state, a["JOINTS_1"], true); + PackedInt32Array joints_0 = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true); + PackedInt32Array joints_1 = _decode_accessor_as_ints(p_state, a["JOINTS_1"], true); ERR_FAIL_COND_V(joints_0.size() != joints_1.size(), ERR_INVALID_DATA); int32_t weight_8_count = JOINT_GROUP_SIZE * 2; Vector<int> joints; @@ -2695,7 +2688,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { array[Mesh::ARRAY_BONES] = joints; } if (a.has("WEIGHTS_0") && !a.has("WEIGHTS_1")) { - Vector<float> weights = _decode_accessor_as_floats(state, a["WEIGHTS_0"], true); + Vector<float> weights = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true); { //gltf does not seem to normalize the weights for some reason.. int wc = weights.size(); float *w = weights.ptrw(); @@ -2716,8 +2709,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } array[Mesh::ARRAY_WEIGHTS] = weights; } else if (a.has("WEIGHTS_0") && a.has("WEIGHTS_1")) { - Vector<float> weights_0 = _decode_accessor_as_floats(state, a["WEIGHTS_0"], true); - Vector<float> weights_1 = _decode_accessor_as_floats(state, a["WEIGHTS_1"], true); + Vector<float> weights_0 = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true); + Vector<float> weights_1 = _decode_accessor_as_floats(p_state, a["WEIGHTS_1"], true); Vector<float> weights; ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA); int32_t weight_8_count = JOINT_GROUP_SIZE * 2; @@ -2762,7 +2755,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } if (p.has("indices")) { - Vector<int> indices = _decode_accessor_as_ints(state, p["indices"], false); + Vector<int> indices = _decode_accessor_as_ints(p_state, p["indices"], false); if (primitive == Mesh::PRIMITIVE_TRIANGLES) { //swap around indices, convert ccw to cw for front face @@ -2836,7 +2829,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } if (t.has("POSITION")) { - Vector<Vector3> varr = _decode_accessor_as_vec3(state, t["POSITION"], true); + Vector<Vector3> varr = _decode_accessor_as_vec3(p_state, t["POSITION"], true); const Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX]; const int size = src_varr.size(); ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR); @@ -2858,7 +2851,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { array_copy[Mesh::ARRAY_VERTEX] = varr; } if (t.has("NORMAL")) { - Vector<Vector3> narr = _decode_accessor_as_vec3(state, t["NORMAL"], true); + Vector<Vector3> narr = _decode_accessor_as_vec3(p_state, t["NORMAL"], true); const Vector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL]; int size = src_narr.size(); ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR); @@ -2880,7 +2873,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { array_copy[Mesh::ARRAY_NORMAL] = narr; } if (t.has("TANGENT")) { - const Vector<Vector3> tangents_v3 = _decode_accessor_as_vec3(state, t["TANGENT"], true); + const Vector<Vector3> tangents_v3 = _decode_accessor_as_vec3(p_state, t["TANGENT"], true); const Vector<float> src_tangents = array[Mesh::ARRAY_TANGENT]; ERR_FAIL_COND_V(src_tangents.size() == 0, ERR_PARSE_ERROR); @@ -2936,16 +2929,18 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } } - Ref<BaseMaterial3D> mat; + Ref<Material> mat; String mat_name; - if (!state->discard_meshes_and_materials) { + if (!p_state->discard_meshes_and_materials) { if (p.has("material")) { const int material = p["material"]; - ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT); - Ref<BaseMaterial3D> mat3d = state->materials[material]; + ERR_FAIL_INDEX_V(material, p_state->materials.size(), ERR_FILE_CORRUPT); + Ref<Material> mat3d = p_state->materials[material]; ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT); - if (has_vertex_color) { - mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + + Ref<BaseMaterial3D> base_material = mat3d; + if (has_vertex_color && base_material.is_valid()) { + base_material->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); } mat = mat3d; @@ -2953,7 +2948,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { Ref<StandardMaterial3D> mat3d; mat3d.instantiate(); if (has_vertex_color) { - mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat3d->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); } mat = mat3d; } @@ -2982,22 +2977,22 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { mesh->set_blend_weights(blend_weights); mesh->set_mesh(import_mesh); - state->meshes.push_back(mesh); + p_state->meshes.push_back(mesh); } - print_verbose("glTF: Total meshes: " + itos(state->meshes.size())); + print_verbose("glTF: Total meshes: " + itos(p_state->meshes.size())); return OK; } -Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path) { +Error GLTFDocument::_serialize_images(Ref<GLTFState> p_state, const String &p_path) { Array images; - for (int i = 0; i < state->images.size(); i++) { + for (int i = 0; i < p_state->images.size(); i++) { Dictionary d; - ERR_CONTINUE(state->images[i].is_null()); + ERR_CONTINUE(p_state->images[i].is_null()); - Ref<Image> image = state->images[i]->get_image(); + Ref<Image> image = p_state->images[i]->get_image(); ERR_CONTINUE(image.is_null()); if (p_path.to_lower().ends_with("glb") || p_path.is_empty()) { @@ -3008,8 +3003,8 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path const GLTFBufferIndex bi = 0; bv->buffer = bi; - bv->byte_offset = state->buffers[bi].size(); - ERR_FAIL_INDEX_V(bi, state->buffers.size(), ERR_PARAMETER_RANGE_ERROR); + bv->byte_offset = p_state->buffers[bi].size(); + ERR_FAIL_INDEX_V(bi, p_state->buffers.size(), ERR_PARAMETER_RANGE_ERROR); Vector<uint8_t> buffer; Ref<ImageTexture> img_tex = image; @@ -3020,21 +3015,21 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path ERR_FAIL_COND_V_MSG(err, err, "Can't convert image to PNG."); bv->byte_length = buffer.size(); - state->buffers.write[bi].resize(state->buffers[bi].size() + bv->byte_length); - memcpy(&state->buffers.write[bi].write[bv->byte_offset], buffer.ptr(), buffer.size()); - ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > state->buffers[bi].size(), ERR_FILE_CORRUPT); + p_state->buffers.write[bi].resize(p_state->buffers[bi].size() + bv->byte_length); + memcpy(&p_state->buffers.write[bi].write[bv->byte_offset], buffer.ptr(), buffer.size()); + ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > p_state->buffers[bi].size(), ERR_FILE_CORRUPT); - state->buffer_views.push_back(bv); - bvi = state->buffer_views.size() - 1; + p_state->buffer_views.push_back(bv); + bvi = p_state->buffer_views.size() - 1; d["bufferView"] = bvi; d["mimeType"] = "image/png"; } else { ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER); - String img_name = state->images[i]->get_name(); + String img_name = p_state->images[i]->get_name(); if (img_name.is_empty()) { img_name = itos(i); } - img_name = _gen_unique_name(state, img_name); + img_name = _gen_unique_name(p_state, img_name); img_name = img_name.pad_zeros(3) + ".png"; String texture_dir = "textures"; String path = p_path.get_base_dir(); @@ -3049,25 +3044,25 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path images.push_back(d); } - print_verbose("Total images: " + itos(state->images.size())); + print_verbose("Total images: " + itos(p_state->images.size())); if (!images.size()) { return OK; } - state->json["images"] = images; + p_state->json["images"] = images; return OK; } -Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_path) { - ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER); - if (!state->json.has("images")) { +Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_path) { + ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); + if (!p_state->json.has("images")) { return OK; } // Ref: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#images - const Array &images = state->json["images"]; + const Array &images = p_state->json["images"]; for (int i = 0; i < images.size(); i++) { const Dictionary &d = images[i]; @@ -3105,7 +3100,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat !uri.begins_with("data:image/png;base64") && !uri.begins_with("data:image/jpeg;base64")) { WARN_PRINT(vformat("glTF: Image index '%d' uses an unsupported URI data type: %s. Skipping it.", i, uri)); - state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count. + p_state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count. continue; } data = _parse_base64_uri(uri); @@ -3130,23 +3125,23 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat // the material), so we do this only as fallback. Ref<Texture2D> texture = ResourceLoader::load(uri); if (texture.is_valid()) { - state->images.push_back(texture); + p_state->images.push_back(texture); continue; } else if (mimetype == "image/png" || mimetype == "image/jpeg") { // Fallback to loading as byte array. // This enables us to support the spec's requirement that we honor mimetype // regardless of file URI. - data = FileAccess::get_file_as_array(uri); + data = FileAccess::get_file_as_bytes(uri); if (data.size() == 0) { WARN_PRINT(vformat("glTF: Image index '%d' couldn't be loaded as a buffer of MIME type '%s' from URI: %s. Skipping it.", i, mimetype, uri)); - state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count. + p_state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count. continue; } data_ptr = data.ptr(); data_size = data.size(); } else { WARN_PRINT(vformat("glTF: Image index '%d' couldn't be loaded from URI: %s. Skipping it.", i, uri)); - state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count. + p_state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count. continue; } } @@ -3157,16 +3152,16 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat const GLTFBufferViewIndex bvi = d["bufferView"]; - ERR_FAIL_INDEX_V(bvi, state->buffer_views.size(), ERR_PARAMETER_RANGE_ERROR); + ERR_FAIL_INDEX_V(bvi, p_state->buffer_views.size(), ERR_PARAMETER_RANGE_ERROR); - Ref<GLTFBufferView> bv = state->buffer_views[bvi]; + Ref<GLTFBufferView> bv = p_state->buffer_views[bvi]; const GLTFBufferIndex bi = bv->buffer; - ERR_FAIL_INDEX_V(bi, state->buffers.size(), ERR_PARAMETER_RANGE_ERROR); + ERR_FAIL_INDEX_V(bi, p_state->buffers.size(), ERR_PARAMETER_RANGE_ERROR); - ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > state->buffers[bi].size(), ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > p_state->buffers[bi].size(), ERR_FILE_CORRUPT); - data_ptr = &state->buffers[bi][bv->byte_offset]; + data_ptr = &p_state->buffers[bi][bv->byte_offset]; data_size = bv->byte_length; } @@ -3199,26 +3194,26 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat // Now we've done our best, fix your scenes. if (img.is_null()) { ERR_PRINT(vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype)); - state->images.push_back(Ref<Texture2D>()); + p_state->images.push_back(Ref<Texture2D>()); continue; } - state->images.push_back(ImageTexture::create_from_image(img)); + p_state->images.push_back(ImageTexture::create_from_image(img)); } - print_verbose("glTF: Total images: " + itos(state->images.size())); + print_verbose("glTF: Total images: " + itos(p_state->images.size())); return OK; } -Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) { - if (!state->textures.size()) { +Error GLTFDocument::_serialize_textures(Ref<GLTFState> p_state) { + if (!p_state->textures.size()) { return OK; } Array textures; - for (int32_t i = 0; i < state->textures.size(); i++) { + for (int32_t i = 0; i < p_state->textures.size(); i++) { Dictionary d; - Ref<GLTFTexture> t = state->textures[i]; + Ref<GLTFTexture> t = p_state->textures[i]; ERR_CONTINUE(t->get_src_image() == -1); d["source"] = t->get_src_image(); @@ -3228,17 +3223,17 @@ Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) { } textures.push_back(d); } - state->json["textures"] = textures; + p_state->json["textures"] = textures; return OK; } -Error GLTFDocument::_parse_textures(Ref<GLTFState> state) { - if (!state->json.has("textures")) { +Error GLTFDocument::_parse_textures(Ref<GLTFState> p_state) { + if (!p_state->json.has("textures")) { return OK; } - const Array &textures = state->json["textures"]; + const Array &textures = p_state->json["textures"]; for (GLTFTextureIndex i = 0; i < textures.size(); i++) { const Dictionary &d = textures[i]; @@ -3252,96 +3247,96 @@ Error GLTFDocument::_parse_textures(Ref<GLTFState> state) { } else { t->set_sampler(-1); } - state->textures.push_back(t); + p_state->textures.push_back(t); } return OK; } -GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) { +GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> p_state, Ref<Texture2D> p_texture, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) { ERR_FAIL_COND_V(p_texture.is_null(), -1); Ref<GLTFTexture> gltf_texture; gltf_texture.instantiate(); ERR_FAIL_COND_V(p_texture->get_image().is_null(), -1); - GLTFImageIndex gltf_src_image_i = state->images.size(); - state->images.push_back(p_texture); + GLTFImageIndex gltf_src_image_i = p_state->images.size(); + p_state->images.push_back(p_texture); gltf_texture->set_src_image(gltf_src_image_i); - gltf_texture->set_sampler(_set_sampler_for_mode(state, p_filter_mode, p_repeats)); - GLTFTextureIndex gltf_texture_i = state->textures.size(); - state->textures.push_back(gltf_texture); + gltf_texture->set_sampler(_set_sampler_for_mode(p_state, p_filter_mode, p_repeats)); + GLTFTextureIndex gltf_texture_i = p_state->textures.size(); + p_state->textures.push_back(gltf_texture); return gltf_texture_i; } -Ref<Texture2D> GLTFDocument::_get_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) { - ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture2D>()); - const GLTFImageIndex image = state->textures[p_texture]->get_src_image(); +Ref<Texture2D> GLTFDocument::_get_texture(Ref<GLTFState> p_state, const GLTFTextureIndex p_texture) { + ERR_FAIL_INDEX_V(p_texture, p_state->textures.size(), Ref<Texture2D>()); + const GLTFImageIndex image = p_state->textures[p_texture]->get_src_image(); - ERR_FAIL_INDEX_V(image, state->images.size(), Ref<Texture2D>()); + ERR_FAIL_INDEX_V(image, p_state->images.size(), Ref<Texture2D>()); - return state->images[image]; + return p_state->images[image]; } -GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref<GLTFState> state, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) { - for (int i = 0; i < state->texture_samplers.size(); ++i) { - if (state->texture_samplers[i]->get_filter_mode() == p_filter_mode) { +GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref<GLTFState> p_state, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) { + for (int i = 0; i < p_state->texture_samplers.size(); ++i) { + if (p_state->texture_samplers[i]->get_filter_mode() == p_filter_mode) { return i; } } - GLTFTextureSamplerIndex gltf_sampler_i = state->texture_samplers.size(); + GLTFTextureSamplerIndex gltf_sampler_i = p_state->texture_samplers.size(); Ref<GLTFTextureSampler> gltf_sampler; gltf_sampler.instantiate(); gltf_sampler->set_filter_mode(p_filter_mode); gltf_sampler->set_wrap_mode(p_repeats); - state->texture_samplers.push_back(gltf_sampler); + p_state->texture_samplers.push_back(gltf_sampler); return gltf_sampler_i; } -Ref<GLTFTextureSampler> GLTFDocument::_get_sampler_for_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) { - ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture2D>()); - const GLTFTextureSamplerIndex sampler = state->textures[p_texture]->get_sampler(); +Ref<GLTFTextureSampler> GLTFDocument::_get_sampler_for_texture(Ref<GLTFState> p_state, const GLTFTextureIndex p_texture) { + ERR_FAIL_INDEX_V(p_texture, p_state->textures.size(), Ref<Texture2D>()); + const GLTFTextureSamplerIndex sampler = p_state->textures[p_texture]->get_sampler(); if (sampler == -1) { - return state->default_texture_sampler; + return p_state->default_texture_sampler; } else { - ERR_FAIL_INDEX_V(sampler, state->texture_samplers.size(), Ref<GLTFTextureSampler>()); + ERR_FAIL_INDEX_V(sampler, p_state->texture_samplers.size(), Ref<GLTFTextureSampler>()); - return state->texture_samplers[sampler]; + return p_state->texture_samplers[sampler]; } } -Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> state) { - if (!state->texture_samplers.size()) { +Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> p_state) { + if (!p_state->texture_samplers.size()) { return OK; } Array samplers; - for (int32_t i = 0; i < state->texture_samplers.size(); ++i) { + for (int32_t i = 0; i < p_state->texture_samplers.size(); ++i) { Dictionary d; - Ref<GLTFTextureSampler> s = state->texture_samplers[i]; + Ref<GLTFTextureSampler> s = p_state->texture_samplers[i]; d["magFilter"] = s->get_mag_filter(); d["minFilter"] = s->get_min_filter(); d["wrapS"] = s->get_wrap_s(); d["wrapT"] = s->get_wrap_t(); samplers.push_back(d); } - state->json["samplers"] = samplers; + p_state->json["samplers"] = samplers; return OK; } -Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> state) { - state->default_texture_sampler.instantiate(); - state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR); - state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR); - state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT); - state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT); +Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> p_state) { + p_state->default_texture_sampler.instantiate(); + p_state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR); + p_state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR); + p_state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT); + p_state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT); - if (!state->json.has("samplers")) { + if (!p_state->json.has("samplers")) { return OK; } - const Array &samplers = state->json["samplers"]; + const Array &samplers = p_state->json["samplers"]; for (int i = 0; i < samplers.size(); ++i) { const Dictionary &d = samplers[i]; @@ -3371,199 +3366,203 @@ Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> state) { sampler->set_wrap_t(GLTFTextureSampler::WrapMode::DEFAULT); } - state->texture_samplers.push_back(sampler); + p_state->texture_samplers.push_back(sampler); } return OK; } -Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { +Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) { Array materials; - for (int32_t i = 0; i < state->materials.size(); i++) { + for (int32_t i = 0; i < p_state->materials.size(); i++) { Dictionary d; - - Ref<BaseMaterial3D> material = state->materials[i]; + Ref<Material> material = p_state->materials[i]; if (material.is_null()) { materials.push_back(d); continue; } if (!material->get_name().is_empty()) { - d["name"] = _gen_unique_name(state, material->get_name()); + d["name"] = _gen_unique_name(p_state, material->get_name()); + } + + Ref<BaseMaterial3D> base_material = material; + if (base_material.is_null()) { + materials.push_back(d); + continue; } + + Dictionary mr; { - Dictionary mr; - { - Array arr; - const Color c = material->get_albedo().srgb_to_linear(); - arr.push_back(c.r); - arr.push_back(c.g); - arr.push_back(c.b); - arr.push_back(c.a); - mr["baseColorFactor"] = arr; - } - { - Dictionary bct; - Ref<Texture2D> albedo_texture = material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO); - GLTFTextureIndex gltf_texture_index = -1; + Array arr; + const Color c = base_material->get_albedo().srgb_to_linear(); + arr.push_back(c.r); + arr.push_back(c.g); + arr.push_back(c.b); + arr.push_back(c.a); + mr["baseColorFactor"] = arr; + } + { + Dictionary bct; + Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO); + GLTFTextureIndex gltf_texture_index = -1; - if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { - albedo_texture->set_name(material->get_name() + "_albedo"); - gltf_texture_index = _set_texture(state, albedo_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); - } - if (gltf_texture_index != -1) { - bct["index"] = gltf_texture_index; - Dictionary extensions = _serialize_texture_transform_uv1(material); - if (!extensions.is_empty()) { - bct["extensions"] = extensions; - state->use_khr_texture_transform = true; - } - mr["baseColorTexture"] = bct; - } + if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { + albedo_texture->set_name(material->get_name() + "_albedo"); + gltf_texture_index = _set_texture(p_state, albedo_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); } - - mr["metallicFactor"] = material->get_metallic(); - mr["roughnessFactor"] = material->get_roughness(); - bool has_roughness = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid(); - bool has_ao = material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid(); - bool has_metalness = material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid(); - if (has_ao || has_roughness || has_metalness) { - Dictionary mrt; - Ref<Texture2D> roughness_texture = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS); - BaseMaterial3D::TextureChannel roughness_channel = material->get_roughness_texture_channel(); - Ref<Texture2D> metallic_texture = material->get_texture(BaseMaterial3D::TEXTURE_METALLIC); - BaseMaterial3D::TextureChannel metalness_channel = material->get_metallic_texture_channel(); - Ref<Texture2D> ao_texture = material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION); - BaseMaterial3D::TextureChannel ao_channel = material->get_ao_texture_channel(); - Ref<ImageTexture> orm_texture; - orm_texture.instantiate(); - Ref<Image> orm_image; - orm_image.instantiate(); - int32_t height = 0; - int32_t width = 0; - Ref<Image> ao_image; - if (has_ao) { - height = ao_texture->get_height(); - width = ao_texture->get_width(); - ao_image = ao_texture->get_image(); - Ref<ImageTexture> img_tex = ao_image; - if (img_tex.is_valid()) { - ao_image = img_tex->get_image(); - } - if (ao_image->is_compressed()) { - ao_image->decompress(); - } + if (gltf_texture_index != -1) { + bct["index"] = gltf_texture_index; + Dictionary extensions = _serialize_texture_transform_uv1(material); + if (!extensions.is_empty()) { + bct["extensions"] = extensions; + p_state->use_khr_texture_transform = true; } - Ref<Image> roughness_image; - if (has_roughness) { - height = roughness_texture->get_height(); - width = roughness_texture->get_width(); - roughness_image = roughness_texture->get_image(); - Ref<ImageTexture> img_tex = roughness_image; - if (img_tex.is_valid()) { - roughness_image = img_tex->get_image(); - } - if (roughness_image->is_compressed()) { - roughness_image->decompress(); - } + mr["baseColorTexture"] = bct; + } + } + + mr["metallicFactor"] = base_material->get_metallic(); + mr["roughnessFactor"] = base_material->get_roughness(); + bool has_roughness = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid(); + bool has_ao = base_material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid(); + bool has_metalness = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid(); + if (has_ao || has_roughness || has_metalness) { + Dictionary mrt; + Ref<Texture2D> roughness_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS); + BaseMaterial3D::TextureChannel roughness_channel = base_material->get_roughness_texture_channel(); + Ref<Texture2D> metallic_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC); + BaseMaterial3D::TextureChannel metalness_channel = base_material->get_metallic_texture_channel(); + Ref<Texture2D> ao_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION); + BaseMaterial3D::TextureChannel ao_channel = base_material->get_ao_texture_channel(); + Ref<ImageTexture> orm_texture; + orm_texture.instantiate(); + Ref<Image> orm_image; + orm_image.instantiate(); + int32_t height = 0; + int32_t width = 0; + Ref<Image> ao_image; + if (has_ao) { + height = ao_texture->get_height(); + width = ao_texture->get_width(); + ao_image = ao_texture->get_image(); + Ref<ImageTexture> img_tex = ao_image; + if (img_tex.is_valid()) { + ao_image = img_tex->get_image(); } - Ref<Image> metallness_image; - if (has_metalness) { - height = metallic_texture->get_height(); - width = metallic_texture->get_width(); - metallness_image = metallic_texture->get_image(); - Ref<ImageTexture> img_tex = metallness_image; - if (img_tex.is_valid()) { - metallness_image = img_tex->get_image(); - } - if (metallness_image->is_compressed()) { - metallness_image->decompress(); - } + if (ao_image->is_compressed()) { + ao_image->decompress(); } - Ref<Texture2D> albedo_texture = material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO); - if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { - height = albedo_texture->get_height(); - width = albedo_texture->get_width(); + } + Ref<Image> roughness_image; + if (has_roughness) { + height = roughness_texture->get_height(); + width = roughness_texture->get_width(); + roughness_image = roughness_texture->get_image(); + Ref<ImageTexture> img_tex = roughness_image; + if (img_tex.is_valid()) { + roughness_image = img_tex->get_image(); } - orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8); - if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) { - ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + if (roughness_image->is_compressed()) { + roughness_image->decompress(); } - if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) { - roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + } + Ref<Image> metallness_image; + if (has_metalness) { + height = metallic_texture->get_height(); + width = metallic_texture->get_width(); + metallness_image = metallic_texture->get_image(); + Ref<ImageTexture> img_tex = metallness_image; + if (img_tex.is_valid()) { + metallness_image = img_tex->get_image(); } - if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) { - metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + if (metallness_image->is_compressed()) { + metallness_image->decompress(); } - for (int32_t h = 0; h < height; h++) { - for (int32_t w = 0; w < width; w++) { - Color c = Color(1.0f, 1.0f, 1.0f); - if (has_ao) { - if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) { - c.r = ao_image->get_pixel(w, h).r; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) { - c.r = ao_image->get_pixel(w, h).g; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) { - c.r = ao_image->get_pixel(w, h).b; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) { - c.r = ao_image->get_pixel(w, h).a; - } + } + Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO); + if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { + height = albedo_texture->get_height(); + width = albedo_texture->get_width(); + } + orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8); + if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) { + ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + } + if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) { + roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + } + if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) { + metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + } + for (int32_t h = 0; h < height; h++) { + for (int32_t w = 0; w < width; w++) { + Color c = Color(1.0f, 1.0f, 1.0f); + if (has_ao) { + if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) { + c.r = ao_image->get_pixel(w, h).r; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) { + c.r = ao_image->get_pixel(w, h).g; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) { + c.r = ao_image->get_pixel(w, h).b; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) { + c.r = ao_image->get_pixel(w, h).a; } - if (has_roughness) { - if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) { - c.g = roughness_image->get_pixel(w, h).r; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) { - c.g = roughness_image->get_pixel(w, h).g; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) { - c.g = roughness_image->get_pixel(w, h).b; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) { - c.g = roughness_image->get_pixel(w, h).a; - } + } + if (has_roughness) { + if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) { + c.g = roughness_image->get_pixel(w, h).r; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) { + c.g = roughness_image->get_pixel(w, h).g; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) { + c.g = roughness_image->get_pixel(w, h).b; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) { + c.g = roughness_image->get_pixel(w, h).a; } - if (has_metalness) { - if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) { - c.b = metallness_image->get_pixel(w, h).r; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) { - c.b = metallness_image->get_pixel(w, h).g; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) { - c.b = metallness_image->get_pixel(w, h).b; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) { - c.b = metallness_image->get_pixel(w, h).a; - } + } + if (has_metalness) { + if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) { + c.b = metallness_image->get_pixel(w, h).r; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) { + c.b = metallness_image->get_pixel(w, h).g; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) { + c.b = metallness_image->get_pixel(w, h).b; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) { + c.b = metallness_image->get_pixel(w, h).a; } - orm_image->set_pixel(w, h, c); } + orm_image->set_pixel(w, h, c); } - orm_image->generate_mipmaps(); - orm_texture->set_image(orm_image); - GLTFTextureIndex orm_texture_index = -1; - if (has_ao || has_roughness || has_metalness) { - orm_texture->set_name(material->get_name() + "_orm"); - orm_texture_index = _set_texture(state, orm_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); - } - if (has_ao) { - Dictionary occt; - occt["index"] = orm_texture_index; - d["occlusionTexture"] = occt; - } - if (has_roughness || has_metalness) { - mrt["index"] = orm_texture_index; - Dictionary extensions = _serialize_texture_transform_uv1(material); - if (!extensions.is_empty()) { - mrt["extensions"] = extensions; - state->use_khr_texture_transform = true; - } - mr["metallicRoughnessTexture"] = mrt; + } + orm_image->generate_mipmaps(); + orm_texture->set_image(orm_image); + GLTFTextureIndex orm_texture_index = -1; + if (has_ao || has_roughness || has_metalness) { + orm_texture->set_name(material->get_name() + "_orm"); + orm_texture_index = _set_texture(p_state, orm_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); + } + if (has_ao) { + Dictionary occt; + occt["index"] = orm_texture_index; + d["occlusionTexture"] = occt; + } + if (has_roughness || has_metalness) { + mrt["index"] = orm_texture_index; + Dictionary extensions = _serialize_texture_transform_uv1(material); + if (!extensions.is_empty()) { + mrt["extensions"] = extensions; + p_state->use_khr_texture_transform = true; } + mr["metallicRoughnessTexture"] = mrt; } - d["pbrMetallicRoughness"] = mr; } - if (material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING)) { + d["pbrMetallicRoughness"] = mr; + if (base_material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING)) { Dictionary nt; Ref<ImageTexture> tex; tex.instantiate(); { - Ref<Texture2D> normal_texture = material->get_texture(BaseMaterial3D::TEXTURE_NORMAL); + Ref<Texture2D> normal_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_NORMAL); if (normal_texture.is_valid()) { // Code for uncompressing RG normal maps Ref<Image> img = normal_texture->get_image(); @@ -3593,30 +3592,31 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { GLTFTextureIndex gltf_texture_index = -1; if (tex.is_valid() && tex->get_image().is_valid()) { tex->set_name(material->get_name() + "_normal"); - gltf_texture_index = _set_texture(state, tex, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); + gltf_texture_index = _set_texture(p_state, tex, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); } - nt["scale"] = material->get_normal_scale(); + nt["scale"] = base_material->get_normal_scale(); if (gltf_texture_index != -1) { nt["index"] = gltf_texture_index; d["normalTexture"] = nt; } } - if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { - const Color c = material->get_emission().linear_to_srgb(); + if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { + const Color c = base_material->get_emission().linear_to_srgb(); Array arr; arr.push_back(c.r); arr.push_back(c.g); arr.push_back(c.b); d["emissiveFactor"] = arr; } - if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { + + if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { Dictionary et; - Ref<Texture2D> emission_texture = material->get_texture(BaseMaterial3D::TEXTURE_EMISSION); + Ref<Texture2D> emission_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_EMISSION); GLTFTextureIndex gltf_texture_index = -1; if (emission_texture.is_valid() && emission_texture->get_image().is_valid()) { emission_texture->set_name(material->get_name() + "_emission"); - gltf_texture_index = _set_texture(state, emission_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); + gltf_texture_index = _set_texture(p_state, emission_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); } if (gltf_texture_index != -1) { @@ -3624,33 +3624,36 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { d["emissiveTexture"] = et; } } - const bool ds = material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED; + + const bool ds = base_material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED; if (ds) { d["doubleSided"] = ds; } - if (material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) { + + if (base_material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) { d["alphaMode"] = "MASK"; - d["alphaCutoff"] = material->get_alpha_scissor_threshold(); - } else if (material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) { + d["alphaCutoff"] = base_material->get_alpha_scissor_threshold(); + } else if (base_material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) { d["alphaMode"] = "BLEND"; } + materials.push_back(d); } if (!materials.size()) { return OK; } - state->json["materials"] = materials; - print_verbose("Total materials: " + itos(state->materials.size())); + p_state->json["materials"] = materials; + print_verbose("Total materials: " + itos(p_state->materials.size())); return OK; } -Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { - if (!state->json.has("materials")) { +Error GLTFDocument::_parse_materials(Ref<GLTFState> p_state) { + if (!p_state->json.has("materials")) { return OK; } - const Array &materials = state->json["materials"]; + const Array &materials = p_state->json["materials"]; for (GLTFMaterialIndex i = 0; i < materials.size(); i++) { const Dictionary &d = materials[i]; @@ -3675,12 +3678,12 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (sgm.has("diffuseTexture")) { const Dictionary &diffuse_texture_dict = sgm["diffuseTexture"]; if (diffuse_texture_dict.has("index")) { - Ref<GLTFTextureSampler> diffuse_sampler = _get_sampler_for_texture(state, diffuse_texture_dict["index"]); + Ref<GLTFTextureSampler> diffuse_sampler = _get_sampler_for_texture(p_state, diffuse_texture_dict["index"]); if (diffuse_sampler.is_valid()) { material->set_texture_filter(diffuse_sampler->get_filter_mode()); material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, diffuse_sampler->get_wrap_mode()); } - Ref<Texture2D> diffuse_texture = _get_texture(state, diffuse_texture_dict["index"]); + Ref<Texture2D> diffuse_texture = _get_texture(p_state, diffuse_texture_dict["index"]); if (diffuse_texture.is_valid()) { spec_gloss->diffuse_img = diffuse_texture->get_image(); material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, diffuse_texture); @@ -3708,7 +3711,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (sgm.has("specularGlossinessTexture")) { const Dictionary &spec_gloss_texture = sgm["specularGlossinessTexture"]; if (spec_gloss_texture.has("index")) { - const Ref<Texture2D> orig_texture = _get_texture(state, spec_gloss_texture["index"]); + const Ref<Texture2D> orig_texture = _get_texture(p_state, spec_gloss_texture["index"]); if (orig_texture.is_valid()) { spec_gloss->spec_gloss_img = orig_texture->get_image(); } @@ -3728,10 +3731,10 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (mr.has("baseColorTexture")) { const Dictionary &bct = mr["baseColorTexture"]; if (bct.has("index")) { - Ref<GLTFTextureSampler> bct_sampler = _get_sampler_for_texture(state, bct["index"]); + Ref<GLTFTextureSampler> bct_sampler = _get_sampler_for_texture(p_state, bct["index"]); material->set_texture_filter(bct_sampler->get_filter_mode()); material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, bct_sampler->get_wrap_mode()); - material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, _get_texture(state, bct["index"])); + material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, _get_texture(p_state, bct["index"])); } if (!mr.has("baseColorFactor")) { material->set_albedo(Color(1, 1, 1)); @@ -3754,7 +3757,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (mr.has("metallicRoughnessTexture")) { const Dictionary &bct = mr["metallicRoughnessTexture"]; if (bct.has("index")) { - const Ref<Texture2D> t = _get_texture(state, bct["index"]); + const Ref<Texture2D> t = _get_texture(p_state, bct["index"]); material->set_texture(BaseMaterial3D::TEXTURE_METALLIC, t); material->set_metallic_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_BLUE); material->set_texture(BaseMaterial3D::TEXTURE_ROUGHNESS, t); @@ -3772,7 +3775,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (d.has("normalTexture")) { const Dictionary &bct = d["normalTexture"]; if (bct.has("index")) { - material->set_texture(BaseMaterial3D::TEXTURE_NORMAL, _get_texture(state, bct["index"])); + material->set_texture(BaseMaterial3D::TEXTURE_NORMAL, _get_texture(p_state, bct["index"])); material->set_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING, true); } if (bct.has("scale")) { @@ -3782,7 +3785,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (d.has("occlusionTexture")) { const Dictionary &bct = d["occlusionTexture"]; if (bct.has("index")) { - material->set_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION, _get_texture(state, bct["index"])); + material->set_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION, _get_texture(p_state, bct["index"])); material->set_ao_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_RED); material->set_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION, true); } @@ -3800,7 +3803,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (d.has("emissiveTexture")) { const Dictionary &bct = d["emissiveTexture"]; if (bct.has("index")) { - material->set_texture(BaseMaterial3D::TEXTURE_EMISSION, _get_texture(state, bct["index"])); + material->set_texture(BaseMaterial3D::TEXTURE_EMISSION, _get_texture(p_state, bct["index"])); material->set_feature(BaseMaterial3D::FEATURE_EMISSION, true); material->set_emission(Color(0, 0, 0)); } @@ -3825,41 +3828,49 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { } } } - state->materials.push_back(material); + p_state->materials.push_back(material); } - print_verbose("Total materials: " + itos(state->materials.size())); + print_verbose("Total materials: " + itos(p_state->materials.size())); return OK; } -void GLTFDocument::_set_texture_transform_uv1(const Dictionary &d, Ref<BaseMaterial3D> material) { - if (d.has("extensions")) { - const Dictionary &extensions = d["extensions"]; +void GLTFDocument::_set_texture_transform_uv1(const Dictionary &p_dict, Ref<BaseMaterial3D> p_material) { + if (p_dict.has("extensions")) { + const Dictionary &extensions = p_dict["extensions"]; if (extensions.has("KHR_texture_transform")) { - const Dictionary &texture_transform = extensions["KHR_texture_transform"]; - const Array &offset_arr = texture_transform["offset"]; - if (offset_arr.size() == 2) { - const Vector3 offset_vector3 = Vector3(offset_arr[0], offset_arr[1], 0.0f); - material->set_uv1_offset(offset_vector3); - } + if (p_material.is_valid()) { + const Dictionary &texture_transform = extensions["KHR_texture_transform"]; + const Array &offset_arr = texture_transform["offset"]; + if (offset_arr.size() == 2) { + const Vector3 offset_vector3 = Vector3(offset_arr[0], offset_arr[1], 0.0f); + p_material->set_uv1_offset(offset_vector3); + } - const Array &scale_arr = texture_transform["scale"]; - if (scale_arr.size() == 2) { - const Vector3 scale_vector3 = Vector3(scale_arr[0], scale_arr[1], 1.0f); - material->set_uv1_scale(scale_vector3); + const Array &scale_arr = texture_transform["scale"]; + if (scale_arr.size() == 2) { + const Vector3 scale_vector3 = Vector3(scale_arr[0], scale_arr[1], 1.0f); + p_material->set_uv1_scale(scale_vector3); + } } } } } void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Ref<BaseMaterial3D> p_material) { + if (r_spec_gloss.is_null()) { + return; + } if (r_spec_gloss->spec_gloss_img.is_null()) { return; } if (r_spec_gloss->diffuse_img.is_null()) { return; } + if (p_material.is_null()) { + return; + } bool has_roughness = false; bool has_metal = false; p_material->set_roughness(1.0f); @@ -3931,13 +3942,13 @@ void GLTFDocument::spec_gloss_to_metal_base_color(const Color &p_specular_factor r_base_color = r_base_color.clamp(); } -GLTFNodeIndex GLTFDocument::_find_highest_node(Ref<GLTFState> state, const Vector<GLTFNodeIndex> &subset) { +GLTFNodeIndex GLTFDocument::_find_highest_node(Ref<GLTFState> p_state, const Vector<GLTFNodeIndex> &p_subset) { int highest = -1; GLTFNodeIndex best_node = -1; - for (int i = 0; i < subset.size(); ++i) { - const GLTFNodeIndex node_i = subset[i]; - const Ref<GLTFNode> node = state->nodes[node_i]; + for (int i = 0; i < p_subset.size(); ++i) { + const GLTFNodeIndex node_i = p_subset[i]; + const Ref<GLTFNode> node = p_state->nodes[node_i]; if (highest == -1 || node->height < highest) { highest = node->height; @@ -3948,38 +3959,38 @@ GLTFNodeIndex GLTFDocument::_find_highest_node(Ref<GLTFState> state, const Vecto return best_node; } -bool GLTFDocument::_capture_nodes_in_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin, const GLTFNodeIndex node_index) { +bool GLTFDocument::_capture_nodes_in_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin, const GLTFNodeIndex p_node_index) { bool found_joint = false; - for (int i = 0; i < state->nodes[node_index]->children.size(); ++i) { - found_joint |= _capture_nodes_in_skin(state, skin, state->nodes[node_index]->children[i]); + for (int i = 0; i < p_state->nodes[p_node_index]->children.size(); ++i) { + found_joint |= _capture_nodes_in_skin(p_state, p_skin, p_state->nodes[p_node_index]->children[i]); } if (found_joint) { // Mark it if we happen to find another skins joint... - if (state->nodes[node_index]->joint && skin->joints.find(node_index) < 0) { - skin->joints.push_back(node_index); - } else if (skin->non_joints.find(node_index) < 0) { - skin->non_joints.push_back(node_index); + if (p_state->nodes[p_node_index]->joint && p_skin->joints.find(p_node_index) < 0) { + p_skin->joints.push_back(p_node_index); + } else if (p_skin->non_joints.find(p_node_index) < 0) { + p_skin->non_joints.push_back(p_node_index); } } - if (skin->joints.find(node_index) > 0) { + if (p_skin->joints.find(p_node_index) > 0) { return true; } return false; } -void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { +void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin) { DisjointSet<GLTFNodeIndex> disjoint_set; - for (int i = 0; i < skin->joints.size(); ++i) { - const GLTFNodeIndex node_index = skin->joints[i]; - const GLTFNodeIndex parent = state->nodes[node_index]->parent; + for (int i = 0; i < p_skin->joints.size(); ++i) { + const GLTFNodeIndex node_index = p_skin->joints[i]; + const GLTFNodeIndex parent = p_state->nodes[node_index]->parent; disjoint_set.insert(node_index); - if (skin->joints.find(parent) >= 0) { + if (p_skin->joints.find(parent) >= 0) { disjoint_set.create_union(parent, node_index); } } @@ -3997,8 +4008,8 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref for (int i = 0; i < roots.size(); ++i) { const GLTFNodeIndex root = roots[i]; - if (maxHeight == -1 || state->nodes[root]->height < maxHeight) { - maxHeight = state->nodes[root]->height; + if (maxHeight == -1 || p_state->nodes[root]->height < maxHeight) { + maxHeight = p_state->nodes[root]->height; } } @@ -4006,13 +4017,13 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref // This sucks, but 99% of all game engines (not just Godot) would have this same issue. for (int i = 0; i < roots.size(); ++i) { GLTFNodeIndex current_node = roots[i]; - while (state->nodes[current_node]->height > maxHeight) { - GLTFNodeIndex parent = state->nodes[current_node]->parent; + while (p_state->nodes[current_node]->height > maxHeight) { + GLTFNodeIndex parent = p_state->nodes[current_node]->parent; - if (state->nodes[parent]->joint && skin->joints.find(parent) < 0) { - skin->joints.push_back(parent); - } else if (skin->non_joints.find(parent) < 0) { - skin->non_joints.push_back(parent); + if (p_state->nodes[parent]->joint && p_skin->joints.find(parent) < 0) { + p_skin->joints.push_back(parent); + } else if (p_skin->non_joints.find(parent) < 0) { + p_skin->non_joints.push_back(parent); } current_node = parent; @@ -4027,21 +4038,21 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref do { all_same = true; - const GLTFNodeIndex first_parent = state->nodes[roots[0]]->parent; + const GLTFNodeIndex first_parent = p_state->nodes[roots[0]]->parent; for (int i = 1; i < roots.size(); ++i) { - all_same &= (first_parent == state->nodes[roots[i]]->parent); + all_same &= (first_parent == p_state->nodes[roots[i]]->parent); } if (!all_same) { for (int i = 0; i < roots.size(); ++i) { const GLTFNodeIndex current_node = roots[i]; - const GLTFNodeIndex parent = state->nodes[current_node]->parent; + const GLTFNodeIndex parent = p_state->nodes[current_node]->parent; - if (state->nodes[parent]->joint && skin->joints.find(parent) < 0) { - skin->joints.push_back(parent); - } else if (skin->non_joints.find(parent) < 0) { - skin->non_joints.push_back(parent); + if (p_state->nodes[parent]->joint && p_skin->joints.find(parent) < 0) { + p_skin->joints.push_back(parent); + } else if (p_skin->non_joints.find(parent) < 0) { + p_skin->non_joints.push_back(parent); } roots.write[i] = parent; @@ -4051,19 +4062,19 @@ void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref } while (!all_same); } -Error GLTFDocument::_expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { - _capture_nodes_for_multirooted_skin(state, skin); +Error GLTFDocument::_expand_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin) { + _capture_nodes_for_multirooted_skin(p_state, p_skin); // Grab all nodes that lay in between skin joints/nodes DisjointSet<GLTFNodeIndex> disjoint_set; Vector<GLTFNodeIndex> all_skin_nodes; - all_skin_nodes.append_array(skin->joints); - all_skin_nodes.append_array(skin->non_joints); + all_skin_nodes.append_array(p_skin->joints); + all_skin_nodes.append_array(p_skin->non_joints); for (int i = 0; i < all_skin_nodes.size(); ++i) { const GLTFNodeIndex node_index = all_skin_nodes[i]; - const GLTFNodeIndex parent = state->nodes[node_index]->parent; + const GLTFNodeIndex parent = p_state->nodes[node_index]->parent; disjoint_set.insert(node_index); if (all_skin_nodes.find(parent) >= 0) { @@ -4080,7 +4091,7 @@ Error GLTFDocument::_expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { Vector<GLTFNodeIndex> set; disjoint_set.get_members(set, out_owners[i]); - const GLTFNodeIndex root = _find_highest_node(state, set); + const GLTFNodeIndex root = _find_highest_node(p_state, set); ERR_FAIL_COND_V(root < 0, FAILED); out_roots.push_back(root); } @@ -4088,15 +4099,15 @@ Error GLTFDocument::_expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { out_roots.sort(); for (int i = 0; i < out_roots.size(); ++i) { - _capture_nodes_in_skin(state, skin, out_roots[i]); + _capture_nodes_in_skin(p_state, p_skin, out_roots[i]); } - skin->roots = out_roots; + p_skin->roots = out_roots; return OK; } -Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { +Error GLTFDocument::_verify_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin) { // This may seem duplicated from expand_skins, but this is really a sanity check! (so it kinda is) // In case additional interpolating logic is added to the skins, this will help ensure that you // do not cause it to self implode into a fiery blaze @@ -4108,12 +4119,12 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { DisjointSet<GLTFNodeIndex> disjoint_set; Vector<GLTFNodeIndex> all_skin_nodes; - all_skin_nodes.append_array(skin->joints); - all_skin_nodes.append_array(skin->non_joints); + all_skin_nodes.append_array(p_skin->joints); + all_skin_nodes.append_array(p_skin->non_joints); for (int i = 0; i < all_skin_nodes.size(); ++i) { const GLTFNodeIndex node_index = all_skin_nodes[i]; - const GLTFNodeIndex parent = state->nodes[node_index]->parent; + const GLTFNodeIndex parent = p_state->nodes[node_index]->parent; disjoint_set.insert(node_index); if (all_skin_nodes.find(parent) >= 0) { @@ -4130,7 +4141,7 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { Vector<GLTFNodeIndex> set; disjoint_set.get_members(set, out_owners[i]); - const GLTFNodeIndex root = _find_highest_node(state, set); + const GLTFNodeIndex root = _find_highest_node(p_state, set); ERR_FAIL_COND_V(root < 0, FAILED); out_roots.push_back(root); } @@ -4140,9 +4151,9 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { ERR_FAIL_COND_V(out_roots.size() == 0, FAILED); // Make sure the roots are the exact same (they better be) - ERR_FAIL_COND_V(out_roots.size() != skin->roots.size(), FAILED); + ERR_FAIL_COND_V(out_roots.size() != p_skin->roots.size(), FAILED); for (int i = 0; i < out_roots.size(); ++i) { - ERR_FAIL_COND_V(out_roots[i] != skin->roots[i], FAILED); + ERR_FAIL_COND_V(out_roots[i] != p_skin->roots[i], FAILED); } // Single rooted skin? Perfectly ok! @@ -4151,9 +4162,9 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { } // Make sure all parents of a multi-rooted skin are the SAME - const GLTFNodeIndex parent = state->nodes[out_roots[0]]->parent; + const GLTFNodeIndex parent = p_state->nodes[out_roots[0]]->parent; for (int i = 1; i < out_roots.size(); ++i) { - if (state->nodes[out_roots[i]]->parent != parent) { + if (p_state->nodes[out_roots[i]]->parent != parent) { return FAILED; } } @@ -4161,12 +4172,12 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { return OK; } -Error GLTFDocument::_parse_skins(Ref<GLTFState> state) { - if (!state->json.has("skins")) { +Error GLTFDocument::_parse_skins(Ref<GLTFState> p_state) { + if (!p_state->json.has("skins")) { return OK; } - const Array &skins = state->json["skins"]; + const Array &skins = p_state->json["skins"]; // Create the base skins, and mark nodes that are joints for (int i = 0; i < skins.size(); i++) { @@ -4180,18 +4191,18 @@ Error GLTFDocument::_parse_skins(Ref<GLTFState> state) { const Array &joints = d["joints"]; if (d.has("inverseBindMatrices")) { - skin->inverse_binds = _decode_accessor_as_xform(state, d["inverseBindMatrices"], false); + skin->inverse_binds = _decode_accessor_as_xform(p_state, d["inverseBindMatrices"], false); ERR_FAIL_COND_V(skin->inverse_binds.size() != joints.size(), ERR_PARSE_ERROR); } for (int j = 0; j < joints.size(); j++) { const GLTFNodeIndex node = joints[j]; - ERR_FAIL_INDEX_V(node, state->nodes.size(), ERR_PARSE_ERROR); + ERR_FAIL_INDEX_V(node, p_state->nodes.size(), ERR_PARSE_ERROR); skin->joints.push_back(node); skin->joints_original.push_back(node); - state->nodes.write[node]->joint = true; + p_state->nodes.write[node]->joint = true; } if (d.has("name") && !String(d["name"]).is_empty()) { @@ -4204,32 +4215,32 @@ Error GLTFDocument::_parse_skins(Ref<GLTFState> state) { skin->skin_root = d["skeleton"]; } - state->skins.push_back(skin); + p_state->skins.push_back(skin); } - for (GLTFSkinIndex i = 0; i < state->skins.size(); ++i) { - Ref<GLTFSkin> skin = state->skins.write[i]; + for (GLTFSkinIndex i = 0; i < p_state->skins.size(); ++i) { + Ref<GLTFSkin> skin = p_state->skins.write[i]; // Expand the skin to capture all the extra non-joints that lie in between the actual joints, // and expand the hierarchy to ensure multi-rooted trees lie on the same height level - ERR_FAIL_COND_V(_expand_skin(state, skin), ERR_PARSE_ERROR); - ERR_FAIL_COND_V(_verify_skin(state, skin), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(_expand_skin(p_state, skin), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(_verify_skin(p_state, skin), ERR_PARSE_ERROR); } - print_verbose("glTF: Total skins: " + itos(state->skins.size())); + print_verbose("glTF: Total skins: " + itos(p_state->skins.size())); return OK; } -Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) { +Error GLTFDocument::_determine_skeletons(Ref<GLTFState> p_state) { // Using a disjoint set, we are going to potentially combine all skins that are actually branches // of a main skeleton, or treat skins defining the same set of nodes as ONE skeleton. // This is another unclear issue caused by the current glTF specification. DisjointSet<GLTFNodeIndex> skeleton_sets; - for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) { - const Ref<GLTFSkin> skin = state->skins[skin_i]; + for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) { + const Ref<GLTFSkin> skin = p_state->skins[skin_i]; Vector<GLTFNodeIndex> all_skin_nodes; all_skin_nodes.append_array(skin->joints); @@ -4237,7 +4248,7 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) { for (int i = 0; i < all_skin_nodes.size(); ++i) { const GLTFNodeIndex node_index = all_skin_nodes[i]; - const GLTFNodeIndex parent = state->nodes[node_index]->parent; + const GLTFNodeIndex parent = p_state->nodes[node_index]->parent; skeleton_sets.insert(node_index); if (all_skin_nodes.find(parent) >= 0) { @@ -4261,7 +4272,7 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) { for (int i = 0; i < groups_representatives.size(); ++i) { Vector<GLTFNodeIndex> group; skeleton_sets.get_members(group, groups_representatives[i]); - highest_group_members.push_back(_find_highest_node(state, group)); + highest_group_members.push_back(_find_highest_node(p_state, group)); groups.push_back(group); } @@ -4273,13 +4284,13 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) { const GLTFNodeIndex node_j = highest_group_members[j]; // Even if they are siblings under the root! :) - if (state->nodes[node_i]->parent == state->nodes[node_j]->parent) { + if (p_state->nodes[node_i]->parent == p_state->nodes[node_j]->parent) { skeleton_sets.create_union(node_i, node_j); } } // Attach any parenting going on together (we need to do this n^2 times) - const GLTFNodeIndex node_i_parent = state->nodes[node_i]->parent; + const GLTFNodeIndex node_i_parent = p_state->nodes[node_i]->parent; if (node_i_parent >= 0) { for (int j = 0; j < groups.size() && i != j; ++j) { const Vector<GLTFNodeIndex> &group = groups[j]; @@ -4306,8 +4317,8 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) { Vector<GLTFNodeIndex> skeleton_nodes; skeleton_sets.get_members(skeleton_nodes, skeleton_owner); - for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) { - Ref<GLTFSkin> skin = state->skins.write[skin_i]; + for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) { + Ref<GLTFSkin> skin = p_state->skins.write[skin_i]; // If any of the the skeletons nodes exist in a skin, that skin now maps to the skeleton for (int i = 0; i < skeleton_nodes.size(); ++i) { @@ -4323,37 +4334,37 @@ Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) { for (int i = 0; i < skeleton_nodes.size(); ++i) { const GLTFNodeIndex node_i = skeleton_nodes[i]; - if (state->nodes[node_i]->joint) { + if (p_state->nodes[node_i]->joint) { skeleton->joints.push_back(node_i); } else { non_joints.push_back(node_i); } } - state->skeletons.push_back(skeleton); + p_state->skeletons.push_back(skeleton); - _reparent_non_joint_skeleton_subtrees(state, state->skeletons.write[skel_i], non_joints); + _reparent_non_joint_skeleton_subtrees(p_state, p_state->skeletons.write[skel_i], non_joints); } - for (GLTFSkeletonIndex skel_i = 0; skel_i < state->skeletons.size(); ++skel_i) { - Ref<GLTFSkeleton> skeleton = state->skeletons.write[skel_i]; + for (GLTFSkeletonIndex skel_i = 0; skel_i < p_state->skeletons.size(); ++skel_i) { + Ref<GLTFSkeleton> skeleton = p_state->skeletons.write[skel_i]; for (int i = 0; i < skeleton->joints.size(); ++i) { const GLTFNodeIndex node_i = skeleton->joints[i]; - Ref<GLTFNode> node = state->nodes[node_i]; + Ref<GLTFNode> node = p_state->nodes[node_i]; ERR_FAIL_COND_V(!node->joint, ERR_PARSE_ERROR); ERR_FAIL_COND_V(node->skeleton >= 0, ERR_PARSE_ERROR); node->skeleton = skel_i; } - ERR_FAIL_COND_V(_determine_skeleton_roots(state, skel_i), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(_determine_skeleton_roots(p_state, skel_i), ERR_PARSE_ERROR); } return OK; } -Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton, const Vector<GLTFNodeIndex> &non_joints) { +Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> p_state, Ref<GLTFSkeleton> p_skeleton, const Vector<GLTFNodeIndex> &p_non_joints) { DisjointSet<GLTFNodeIndex> subtree_set; // Populate the disjoint set with ONLY non joints that are in the skeleton hierarchy (non_joints vector) @@ -4364,13 +4375,13 @@ Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> state, // skinD depicted here explains this issue: // https://github.com/KhronosGroup/glTF-Asset-Generator/blob/master/Output/Positive/Animation_Skin - for (int i = 0; i < non_joints.size(); ++i) { - const GLTFNodeIndex node_i = non_joints[i]; + for (int i = 0; i < p_non_joints.size(); ++i) { + const GLTFNodeIndex node_i = p_non_joints[i]; subtree_set.insert(node_i); - const GLTFNodeIndex parent_i = state->nodes[node_i]->parent; - if (parent_i >= 0 && non_joints.find(parent_i) >= 0 && !state->nodes[parent_i]->joint) { + const GLTFNodeIndex parent_i = p_state->nodes[node_i]->parent; + if (parent_i >= 0 && p_non_joints.find(parent_i) >= 0 && !p_state->nodes[parent_i]->joint) { subtree_set.create_union(parent_i, node_i); } } @@ -4387,34 +4398,34 @@ Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> state, subtree_set.get_members(subtree_nodes, subtree_root); for (int subtree_i = 0; subtree_i < subtree_nodes.size(); ++subtree_i) { - Ref<GLTFNode> node = state->nodes[subtree_nodes[subtree_i]]; + Ref<GLTFNode> node = p_state->nodes[subtree_nodes[subtree_i]]; node->joint = true; // Add the joint to the skeletons joints - skeleton->joints.push_back(subtree_nodes[subtree_i]); + p_skeleton->joints.push_back(subtree_nodes[subtree_i]); } } return OK; } -Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i) { +Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> p_state, const GLTFSkeletonIndex p_skel_i) { DisjointSet<GLTFNodeIndex> disjoint_set; - for (GLTFNodeIndex i = 0; i < state->nodes.size(); ++i) { - const Ref<GLTFNode> node = state->nodes[i]; + for (GLTFNodeIndex i = 0; i < p_state->nodes.size(); ++i) { + const Ref<GLTFNode> node = p_state->nodes[i]; - if (node->skeleton != skel_i) { + if (node->skeleton != p_skel_i) { continue; } disjoint_set.insert(i); - if (node->parent >= 0 && state->nodes[node->parent]->skeleton == skel_i) { + if (node->parent >= 0 && p_state->nodes[node->parent]->skeleton == p_skel_i) { disjoint_set.create_union(node->parent, i); } } - Ref<GLTFSkeleton> skeleton = state->skeletons.write[skel_i]; + Ref<GLTFSkeleton> skeleton = p_state->skeletons.write[p_skel_i]; Vector<GLTFNodeIndex> representatives; disjoint_set.get_representatives(representatives); @@ -4424,7 +4435,7 @@ Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSk for (int i = 0; i < representatives.size(); ++i) { Vector<GLTFNodeIndex> set; disjoint_set.get_members(set, representatives[i]); - const GLTFNodeIndex root = _find_highest_node(state, set); + const GLTFNodeIndex root = _find_highest_node(p_state, set); ERR_FAIL_COND_V(root < 0, FAILED); roots.push_back(root); } @@ -4440,9 +4451,9 @@ Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSk } // Check that the subtrees have the same parent root - const GLTFNodeIndex parent = state->nodes[roots[0]]->parent; + const GLTFNodeIndex parent = p_state->nodes[roots[0]]->parent; for (int i = 1; i < roots.size(); ++i) { - if (state->nodes[roots[i]]->parent != parent) { + if (p_state->nodes[roots[i]]->parent != parent) { return FAILED; } } @@ -4450,16 +4461,16 @@ Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSk return OK; } -Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) { - for (GLTFSkeletonIndex skel_i = 0; skel_i < state->skeletons.size(); ++skel_i) { - Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i]; +Error GLTFDocument::_create_skeletons(Ref<GLTFState> p_state) { + for (GLTFSkeletonIndex skel_i = 0; skel_i < p_state->skeletons.size(); ++skel_i) { + Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_i]; Skeleton3D *skeleton = memnew(Skeleton3D); gltf_skeleton->godot_skeleton = skeleton; - state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skel_i; + p_state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skel_i; // Make a unique name, no gltf node represents this skeleton - skeleton->set_name(_gen_unique_name(state, "Skeleton3D")); + skeleton->set_name(_gen_unique_name(p_state, "Skeleton3D")); List<GLTFNodeIndex> bones; @@ -4475,14 +4486,14 @@ Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) { const GLTFNodeIndex node_i = bones.front()->get(); bones.pop_front(); - Ref<GLTFNode> node = state->nodes[node_i]; + Ref<GLTFNode> node = p_state->nodes[node_i]; ERR_FAIL_COND_V(node->skeleton != skel_i, FAILED); { // Add all child nodes to the stack (deterministically) Vector<GLTFNodeIndex> child_nodes; for (int i = 0; i < node->children.size(); ++i) { const GLTFNodeIndex child_i = node->children[i]; - if (state->nodes[child_i]->skeleton == skel_i) { + if (p_state->nodes[child_i]->skeleton == skel_i) { child_nodes.push_back(child_i); } } @@ -4500,7 +4511,7 @@ Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) { node->set_name("bone"); } - node->set_name(_gen_unique_bone_name(state, skel_i, node->get_name())); + node->set_name(_gen_unique_bone_name(p_state, skel_i, node->get_name())); skeleton->add_bone(node->get_name()); skeleton->set_bone_rest(bone_index, node->xform); @@ -4508,30 +4519,30 @@ Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) { skeleton->set_bone_pose_rotation(bone_index, node->rotation.normalized()); skeleton->set_bone_pose_scale(bone_index, node->scale); - if (node->parent >= 0 && state->nodes[node->parent]->skeleton == skel_i) { - const int bone_parent = skeleton->find_bone(state->nodes[node->parent]->get_name()); + if (node->parent >= 0 && p_state->nodes[node->parent]->skeleton == skel_i) { + const int bone_parent = skeleton->find_bone(p_state->nodes[node->parent]->get_name()); ERR_FAIL_COND_V(bone_parent < 0, FAILED); - skeleton->set_bone_parent(bone_index, skeleton->find_bone(state->nodes[node->parent]->get_name())); + skeleton->set_bone_parent(bone_index, skeleton->find_bone(p_state->nodes[node->parent]->get_name())); } - state->scene_nodes.insert(node_i, skeleton); + p_state->scene_nodes.insert(node_i, skeleton); } } - ERR_FAIL_COND_V(_map_skin_joints_indices_to_skeleton_bone_indices(state), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(_map_skin_joints_indices_to_skeleton_bone_indices(p_state), ERR_PARSE_ERROR); return OK; } -Error GLTFDocument::_map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFState> state) { - for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) { - Ref<GLTFSkin> skin = state->skins.write[skin_i]; +Error GLTFDocument::_map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFState> p_state) { + for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) { + Ref<GLTFSkin> skin = p_state->skins.write[skin_i]; - Ref<GLTFSkeleton> skeleton = state->skeletons[skin->skeleton]; + Ref<GLTFSkeleton> skeleton = p_state->skeletons[skin->skeleton]; for (int joint_index = 0; joint_index < skin->joints_original.size(); ++joint_index) { const GLTFNodeIndex node_i = skin->joints_original[joint_index]; - const Ref<GLTFNode> node = state->nodes[node_i]; + const Ref<GLTFNode> node = p_state->nodes[node_i]; const int bone_index = skeleton->godot_skeleton->find_bone(node->get_name()); ERR_FAIL_COND_V(bone_index < 0, FAILED); @@ -4543,28 +4554,28 @@ Error GLTFDocument::_map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFSt return OK; } -Error GLTFDocument::_serialize_skins(Ref<GLTFState> state) { - _remove_duplicate_skins(state); +Error GLTFDocument::_serialize_skins(Ref<GLTFState> p_state) { + _remove_duplicate_skins(p_state); Array json_skins; - for (int skin_i = 0; skin_i < state->skins.size(); skin_i++) { - Ref<GLTFSkin> gltf_skin = state->skins[skin_i]; + for (int skin_i = 0; skin_i < p_state->skins.size(); skin_i++) { + Ref<GLTFSkin> gltf_skin = p_state->skins[skin_i]; Dictionary json_skin; - json_skin["inverseBindMatrices"] = _encode_accessor_as_xform(state, gltf_skin->inverse_binds, false); + json_skin["inverseBindMatrices"] = _encode_accessor_as_xform(p_state, gltf_skin->inverse_binds, false); json_skin["joints"] = gltf_skin->get_joints(); json_skin["name"] = gltf_skin->get_name(); json_skins.push_back(json_skin); } - if (!state->skins.size()) { + if (!p_state->skins.size()) { return OK; } - state->json["skins"] = json_skins; + p_state->json["skins"] = json_skins; return OK; } -Error GLTFDocument::_create_skins(Ref<GLTFState> state) { - for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) { - Ref<GLTFSkin> gltf_skin = state->skins.write[skin_i]; +Error GLTFDocument::_create_skins(Ref<GLTFState> p_state) { + for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) { + Ref<GLTFSkin> gltf_skin = p_state->skins.write[skin_i]; Ref<Skin> skin; skin.instantiate(); @@ -4574,14 +4585,14 @@ Error GLTFDocument::_create_skins(Ref<GLTFState> state) { for (int joint_i = 0; joint_i < gltf_skin->joints_original.size(); ++joint_i) { GLTFNodeIndex node = gltf_skin->joints_original[joint_i]; - String bone_name = state->nodes[node]->get_name(); + String bone_name = p_state->nodes[node]->get_name(); Transform3D xform; if (has_ibms) { xform = gltf_skin->inverse_binds[joint_i]; } - if (state->use_named_skin_binds) { + if (p_state->use_named_skin_binds) { skin->add_named_bind(bone_name, xform); } else { int32_t bone_i = gltf_skin->joint_i_to_bone_i[joint_i]; @@ -4593,35 +4604,35 @@ Error GLTFDocument::_create_skins(Ref<GLTFState> state) { } // Purge the duplicates! - _remove_duplicate_skins(state); + _remove_duplicate_skins(p_state); // Create unique names now, after removing duplicates - for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) { - Ref<Skin> skin = state->skins.write[skin_i]->godot_skin; + for (GLTFSkinIndex skin_i = 0; skin_i < p_state->skins.size(); ++skin_i) { + Ref<Skin> skin = p_state->skins.write[skin_i]->godot_skin; if (skin->get_name().is_empty()) { // Make a unique name, no gltf node represents this skin - skin->set_name(_gen_unique_name(state, "Skin")); + skin->set_name(_gen_unique_name(p_state, "Skin")); } } return OK; } -bool GLTFDocument::_skins_are_same(const Ref<Skin> skin_a, const Ref<Skin> skin_b) { - if (skin_a->get_bind_count() != skin_b->get_bind_count()) { +bool GLTFDocument::_skins_are_same(const Ref<Skin> p_skin_a, const Ref<Skin> p_skin_b) { + if (p_skin_a->get_bind_count() != p_skin_b->get_bind_count()) { return false; } - for (int i = 0; i < skin_a->get_bind_count(); ++i) { - if (skin_a->get_bind_bone(i) != skin_b->get_bind_bone(i)) { + for (int i = 0; i < p_skin_a->get_bind_count(); ++i) { + if (p_skin_a->get_bind_bone(i) != p_skin_b->get_bind_bone(i)) { return false; } - if (skin_a->get_bind_name(i) != skin_b->get_bind_name(i)) { + if (p_skin_a->get_bind_name(i) != p_skin_b->get_bind_name(i)) { return false; } - Transform3D a_xform = skin_a->get_bind_pose(i); - Transform3D b_xform = skin_b->get_bind_pose(i); + Transform3D a_xform = p_skin_a->get_bind_pose(i); + Transform3D b_xform = p_skin_b->get_bind_pose(i); if (a_xform != b_xform) { return false; @@ -4631,67 +4642,67 @@ bool GLTFDocument::_skins_are_same(const Ref<Skin> skin_a, const Ref<Skin> skin_ return true; } -void GLTFDocument::_remove_duplicate_skins(Ref<GLTFState> state) { - for (int i = 0; i < state->skins.size(); ++i) { - for (int j = i + 1; j < state->skins.size(); ++j) { - const Ref<Skin> skin_i = state->skins[i]->godot_skin; - const Ref<Skin> skin_j = state->skins[j]->godot_skin; +void GLTFDocument::_remove_duplicate_skins(Ref<GLTFState> p_state) { + for (int i = 0; i < p_state->skins.size(); ++i) { + for (int j = i + 1; j < p_state->skins.size(); ++j) { + const Ref<Skin> skin_i = p_state->skins[i]->godot_skin; + const Ref<Skin> skin_j = p_state->skins[j]->godot_skin; if (_skins_are_same(skin_i, skin_j)) { // replace it and delete the old - state->skins.write[j]->godot_skin = skin_i; + p_state->skins.write[j]->godot_skin = skin_i; } } } } -Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) { - if (state->lights.is_empty()) { +Error GLTFDocument::_serialize_lights(Ref<GLTFState> p_state) { + if (p_state->lights.is_empty()) { return OK; } Array lights; - for (GLTFLightIndex i = 0; i < state->lights.size(); i++) { - lights.push_back(state->lights[i]->to_dictionary()); + for (GLTFLightIndex i = 0; i < p_state->lights.size(); i++) { + lights.push_back(p_state->lights[i]->to_dictionary()); } Dictionary extensions; - if (state->json.has("extensions")) { - extensions = state->json["extensions"]; + if (p_state->json.has("extensions")) { + extensions = p_state->json["extensions"]; } else { - state->json["extensions"] = extensions; + p_state->json["extensions"] = extensions; } Dictionary lights_punctual; extensions["KHR_lights_punctual"] = lights_punctual; lights_punctual["lights"] = lights; - print_verbose("glTF: Total lights: " + itos(state->lights.size())); + print_verbose("glTF: Total lights: " + itos(p_state->lights.size())); return OK; } -Error GLTFDocument::_serialize_cameras(Ref<GLTFState> state) { +Error GLTFDocument::_serialize_cameras(Ref<GLTFState> p_state) { Array cameras; - cameras.resize(state->cameras.size()); - for (GLTFCameraIndex i = 0; i < state->cameras.size(); i++) { - cameras[i] = state->cameras[i]->to_dictionary(); + cameras.resize(p_state->cameras.size()); + for (GLTFCameraIndex i = 0; i < p_state->cameras.size(); i++) { + cameras[i] = p_state->cameras[i]->to_dictionary(); } - if (!state->cameras.size()) { + if (!p_state->cameras.size()) { return OK; } - state->json["cameras"] = cameras; + p_state->json["cameras"] = cameras; - print_verbose("glTF: Total cameras: " + itos(state->cameras.size())); + print_verbose("glTF: Total cameras: " + itos(p_state->cameras.size())); return OK; } -Error GLTFDocument::_parse_lights(Ref<GLTFState> state) { - if (!state->json.has("extensions")) { +Error GLTFDocument::_parse_lights(Ref<GLTFState> p_state) { + if (!p_state->json.has("extensions")) { return OK; } - Dictionary extensions = state->json["extensions"]; + Dictionary extensions = p_state->json["extensions"]; if (!extensions.has("KHR_lights_punctual")) { return OK; } @@ -4707,26 +4718,26 @@ Error GLTFDocument::_parse_lights(Ref<GLTFState> state) { if (light.is_null()) { return Error::ERR_PARSE_ERROR; } - state->lights.push_back(light); + p_state->lights.push_back(light); } - print_verbose("glTF: Total lights: " + itos(state->lights.size())); + print_verbose("glTF: Total lights: " + itos(p_state->lights.size())); return OK; } -Error GLTFDocument::_parse_cameras(Ref<GLTFState> state) { - if (!state->json.has("cameras")) { +Error GLTFDocument::_parse_cameras(Ref<GLTFState> p_state) { + if (!p_state->json.has("cameras")) { return OK; } - const Array cameras = state->json["cameras"]; + const Array cameras = p_state->json["cameras"]; for (GLTFCameraIndex i = 0; i < cameras.size(); i++) { - state->cameras.push_back(GLTFCamera::from_dictionary(cameras[i])); + p_state->cameras.push_back(GLTFCamera::from_dictionary(cameras[i])); } - print_verbose("glTF: Total cameras: " + itos(state->cameras.size())); + print_verbose("glTF: Total cameras: " + itos(p_state->cameras.size())); return OK; } @@ -4746,24 +4757,24 @@ String GLTFDocument::interpolation_to_string(const GLTFAnimation::Interpolation return interp; } -Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) { - if (!state->animation_players.size()) { +Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { + if (!p_state->animation_players.size()) { return OK; } - for (int32_t player_i = 0; player_i < state->animation_players.size(); player_i++) { + for (int32_t player_i = 0; player_i < p_state->animation_players.size(); player_i++) { List<StringName> animation_names; - AnimationPlayer *animation_player = state->animation_players[player_i]; + AnimationPlayer *animation_player = p_state->animation_players[player_i]; animation_player->get_animation_list(&animation_names); if (animation_names.size()) { for (int animation_name_i = 0; animation_name_i < animation_names.size(); animation_name_i++) { - _convert_animation(state, animation_player, animation_names[animation_name_i]); + _convert_animation(p_state, animation_player, animation_names[animation_name_i]); } } } Array animations; - for (GLTFAnimationIndex animation_i = 0; animation_i < state->animations.size(); animation_i++) { + for (GLTFAnimationIndex animation_i = 0; animation_i < p_state->animations.size(); animation_i++) { Dictionary d; - Ref<GLTFAnimation> gltf_animation = state->animations[animation_i]; + Ref<GLTFAnimation> gltf_animation = p_state->animations[animation_i]; if (!gltf_animation->get_tracks().size()) { continue; } @@ -4783,9 +4794,9 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) { s["interpolation"] = interpolation_to_string(track.position_track.interpolation); Vector<real_t> times = Variant(track.position_track.times); - s["input"] = _encode_accessor_as_floats(state, times, false); + s["input"] = _encode_accessor_as_floats(p_state, times, false); Vector<Vector3> values = Variant(track.position_track.values); - s["output"] = _encode_accessor_as_vec3(state, values, false); + s["output"] = _encode_accessor_as_vec3(p_state, values, false); samplers.push_back(s); @@ -4803,9 +4814,9 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) { s["interpolation"] = interpolation_to_string(track.rotation_track.interpolation); Vector<real_t> times = Variant(track.rotation_track.times); - s["input"] = _encode_accessor_as_floats(state, times, false); + s["input"] = _encode_accessor_as_floats(p_state, times, false); Vector<Quaternion> values = track.rotation_track.values; - s["output"] = _encode_accessor_as_quaternions(state, values, false); + s["output"] = _encode_accessor_as_quaternions(p_state, values, false); samplers.push_back(s); @@ -4823,9 +4834,9 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) { s["interpolation"] = interpolation_to_string(track.scale_track.interpolation); Vector<real_t> times = Variant(track.scale_track.times); - s["input"] = _encode_accessor_as_floats(state, times, false); + s["input"] = _encode_accessor_as_floats(p_state, times, false); Vector<Vector3> values = Variant(track.scale_track.values); - s["output"] = _encode_accessor_as_vec3(state, values, false); + s["output"] = _encode_accessor_as_vec3(p_state, values, false); samplers.push_back(s); @@ -4903,8 +4914,8 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) { } s["interpolation"] = interpolation_to_string(track.weight_tracks[track.weight_tracks.size() - 1].interpolation); - s["input"] = _encode_accessor_as_floats(state, all_track_times, false); - s["output"] = _encode_accessor_as_floats(state, all_track_values, false); + s["input"] = _encode_accessor_as_floats(p_state, all_track_times, false); + s["output"] = _encode_accessor_as_floats(p_state, all_track_values, false); samplers.push_back(s); @@ -4926,19 +4937,19 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) { if (!animations.size()) { return OK; } - state->json["animations"] = animations; + p_state->json["animations"] = animations; - print_verbose("glTF: Total animations '" + itos(state->animations.size()) + "'."); + print_verbose("glTF: Total animations '" + itos(p_state->animations.size()) + "'."); return OK; } -Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { - if (!state->json.has("animations")) { +Error GLTFDocument::_parse_animations(Ref<GLTFState> p_state) { + if (!p_state->json.has("animations")) { return OK; } - const Array &animations = state->json["animations"]; + const Array &animations = p_state->json["animations"]; for (GLTFAnimationIndex i = 0; i < animations.size(); i++) { const Dictionary &d = animations[i]; @@ -4959,7 +4970,7 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { if (anim_name_lower.begins_with("loop") || anim_name_lower.ends_with("loop") || anim_name_lower.begins_with("cycle") || anim_name_lower.ends_with("cycle")) { animation->set_loop(true); } - animation->set_name(_gen_unique_animation_name(state, anim_name)); + animation->set_name(_gen_unique_animation_name(p_state, anim_name)); } for (int j = 0; j < channels.size(); j++) { @@ -4980,7 +4991,7 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { GLTFNodeIndex node = t["node"]; String path = t["path"]; - ERR_FAIL_INDEX_V(node, state->nodes.size(), ERR_PARSE_ERROR); + ERR_FAIL_INDEX_V(node, p_state->nodes.size(), ERR_PARSE_ERROR); GLTFAnimation::Track *track = nullptr; @@ -5015,27 +5026,27 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { } } - const Vector<float> times = _decode_accessor_as_floats(state, input, false); + const Vector<float> times = _decode_accessor_as_floats(p_state, input, false); if (path == "translation") { - const Vector<Vector3> positions = _decode_accessor_as_vec3(state, output, false); + const Vector<Vector3> positions = _decode_accessor_as_vec3(p_state, output, false); track->position_track.interpolation = interp; track->position_track.times = Variant(times); //convert via variant track->position_track.values = Variant(positions); //convert via variant } else if (path == "rotation") { - const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(state, output, false); + const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(p_state, output, false); track->rotation_track.interpolation = interp; track->rotation_track.times = Variant(times); //convert via variant track->rotation_track.values = rotations; } else if (path == "scale") { - const Vector<Vector3> scales = _decode_accessor_as_vec3(state, output, false); + const Vector<Vector3> scales = _decode_accessor_as_vec3(p_state, output, false); track->scale_track.interpolation = interp; track->scale_track.times = Variant(times); //convert via variant track->scale_track.values = Variant(scales); //convert via variant } else if (path == "weights") { - const Vector<float> weights = _decode_accessor_as_floats(state, output, false); + const Vector<float> weights = _decode_accessor_as_floats(p_state, output, false); - ERR_FAIL_INDEX_V(state->nodes[node]->mesh, state->meshes.size(), ERR_PARSE_ERROR); - Ref<GLTFMesh> mesh = state->meshes[state->nodes[node]->mesh]; + ERR_FAIL_INDEX_V(p_state->nodes[node]->mesh, p_state->meshes.size(), ERR_PARSE_ERROR); + Ref<GLTFMesh> mesh = p_state->meshes[p_state->nodes[node]->mesh]; ERR_CONTINUE(!mesh->get_blend_weights().size()); const int wc = mesh->get_blend_weights().size(); @@ -5063,17 +5074,17 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { } } - state->animations.push_back(animation); + p_state->animations.push_back(animation); } - print_verbose("glTF: Total animations '" + itos(state->animations.size()) + "'."); + print_verbose("glTF: Total animations '" + itos(p_state->animations.size()) + "'."); return OK; } -void GLTFDocument::_assign_scene_names(Ref<GLTFState> state) { - for (int i = 0; i < state->nodes.size(); i++) { - Ref<GLTFNode> n = state->nodes[i]; +void GLTFDocument::_assign_scene_names(Ref<GLTFState> p_state) { + for (int i = 0; i < p_state->nodes.size(); i++) { + Ref<GLTFNode> n = p_state->nodes[i]; // Any joints get unique names generated when the skeleton is made, unique to the skeleton if (n->skeleton >= 0) { @@ -5082,21 +5093,21 @@ void GLTFDocument::_assign_scene_names(Ref<GLTFState> state) { if (n->get_name().is_empty()) { if (n->mesh >= 0) { - n->set_name(_gen_unique_name(state, "Mesh")); + n->set_name(_gen_unique_name(p_state, "Mesh")); } else if (n->camera >= 0) { - n->set_name(_gen_unique_name(state, "Camera3D")); + n->set_name(_gen_unique_name(p_state, "Camera3D")); } else { - n->set_name(_gen_unique_name(state, "Node")); + n->set_name(_gen_unique_name(p_state, "Node")); } } - n->set_name(_gen_unique_name(state, n->get_name())); + n->set_name(_gen_unique_name(p_state, n->get_name())); } } -BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> state, Skeleton3D *skeleton, const GLTFNodeIndex node_index, const GLTFNodeIndex bone_index) { - Ref<GLTFNode> gltf_node = state->nodes[node_index]; - Ref<GLTFNode> bone_node = state->nodes[bone_index]; +BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> p_state, Skeleton3D *p_skeleton, const GLTFNodeIndex p_node_index, const GLTFNodeIndex p_bone_index) { + Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index]; + Ref<GLTFNode> bone_node = p_state->nodes[p_bone_index]; BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D); print_verbose("glTF: Creating bone attachment for: " + gltf_node->get_name()); @@ -5107,7 +5118,7 @@ BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> state, return bone_attachment; } -GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> state, MeshInstance3D *p_mesh_instance) { +GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> p_state, MeshInstance3D *p_mesh_instance) { ERR_FAIL_NULL_V(p_mesh_instance, -1); if (p_mesh_instance->get_mesh().is_null()) { return -1; @@ -5138,20 +5149,20 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> state, MeshInst gltf_mesh->set_instance_materials(instance_materials); gltf_mesh->set_mesh(current_mesh); gltf_mesh->set_blend_weights(blend_weights); - GLTFMeshIndex mesh_i = state->meshes.size(); - state->meshes.push_back(gltf_mesh); + GLTFMeshIndex mesh_i = p_state->meshes.size(); + p_state->meshes.push_back(gltf_mesh); return mesh_i; } -ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> state, const GLTFNodeIndex node_index) { - Ref<GLTFNode> gltf_node = state->nodes[node_index]; +ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) { + Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index]; - ERR_FAIL_INDEX_V(gltf_node->mesh, state->meshes.size(), nullptr); + ERR_FAIL_INDEX_V(gltf_node->mesh, p_state->meshes.size(), nullptr); ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D); print_verbose("glTF: Creating mesh for: " + gltf_node->get_name()); - Ref<GLTFMesh> mesh = state->meshes.write[gltf_node->mesh]; + Ref<GLTFMesh> mesh = p_state->meshes.write[gltf_node->mesh]; if (mesh.is_null()) { return mi; } @@ -5163,56 +5174,56 @@ ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> sta return mi; } -Light3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex node_index) { - Ref<GLTFNode> gltf_node = state->nodes[node_index]; +Light3D *GLTFDocument::_generate_light(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) { + Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index]; - ERR_FAIL_INDEX_V(gltf_node->light, state->lights.size(), nullptr); + ERR_FAIL_INDEX_V(gltf_node->light, p_state->lights.size(), nullptr); print_verbose("glTF: Creating light for: " + gltf_node->get_name()); - Ref<GLTFLight> l = state->lights[gltf_node->light]; + Ref<GLTFLight> l = p_state->lights[gltf_node->light]; return l->to_node(); } -Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> state, const GLTFNodeIndex node_index) { - Ref<GLTFNode> gltf_node = state->nodes[node_index]; +Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) { + Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index]; - ERR_FAIL_INDEX_V(gltf_node->camera, state->cameras.size(), nullptr); + ERR_FAIL_INDEX_V(gltf_node->camera, p_state->cameras.size(), nullptr); print_verbose("glTF: Creating camera for: " + gltf_node->get_name()); - Ref<GLTFCamera> c = state->cameras[gltf_node->camera]; + Ref<GLTFCamera> c = p_state->cameras[gltf_node->camera]; return c->to_node(); } -GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera3D *p_camera) { +GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> p_state, Camera3D *p_camera) { print_verbose("glTF: Converting camera: " + p_camera->get_name()); Ref<GLTFCamera> c = GLTFCamera::from_node(p_camera); - GLTFCameraIndex camera_index = state->cameras.size(); - state->cameras.push_back(c); + GLTFCameraIndex camera_index = p_state->cameras.size(); + p_state->cameras.push_back(c); return camera_index; } -GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> state, Light3D *p_light) { +GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> p_state, Light3D *p_light) { print_verbose("glTF: Converting light: " + p_light->get_name()); Ref<GLTFLight> l = GLTFLight::from_node(p_light); - GLTFLightIndex light_index = state->lights.size(); - state->lights.push_back(l); + GLTFLightIndex light_index = p_state->lights.size(); + p_state->lights.push_back(l); return light_index; } -void GLTFDocument::_convert_spatial(Ref<GLTFState> state, Node3D *p_spatial, Ref<GLTFNode> p_node) { +void GLTFDocument::_convert_spatial(Ref<GLTFState> p_state, Node3D *p_spatial, Ref<GLTFNode> p_node) { Transform3D xform = p_spatial->get_transform(); p_node->scale = xform.basis.get_scale(); p_node->rotation = xform.basis.get_rotation_quaternion(); p_node->position = xform.origin; } -Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> state, const GLTFNodeIndex node_index) { - Ref<GLTFNode> gltf_node = state->nodes[node_index]; +Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index) { + Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index]; Node3D *spatial = memnew(Node3D); print_verbose("glTF: Converting spatial: " + gltf_node->get_name()); @@ -5220,7 +5231,7 @@ Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> state, const GLTFNodeInde return spatial; } -void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, const GLTFNodeIndex p_gltf_parent, const GLTFNodeIndex p_gltf_root) { +void GLTFDocument::_convert_scene_node(Ref<GLTFState> p_state, Node *p_current, const GLTFNodeIndex p_gltf_parent, const GLTFNodeIndex p_gltf_root) { bool retflag = true; _check_visibility(p_current, retflag); if (retflag) { @@ -5228,64 +5239,68 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, co } Ref<GLTFNode> gltf_node; gltf_node.instantiate(); - gltf_node->set_name(_gen_unique_name(state, p_current->get_name())); + gltf_node->set_name(_gen_unique_name(p_state, p_current->get_name())); if (cast_to<Node3D>(p_current)) { Node3D *spatial = cast_to<Node3D>(p_current); - _convert_spatial(state, spatial, gltf_node); + _convert_spatial(p_state, spatial, gltf_node); } if (cast_to<MeshInstance3D>(p_current)) { MeshInstance3D *mi = cast_to<MeshInstance3D>(p_current); - _convert_mesh_instance_to_gltf(mi, state, gltf_node); + _convert_mesh_instance_to_gltf(mi, p_state, gltf_node); } else if (cast_to<BoneAttachment3D>(p_current)) { BoneAttachment3D *bone = cast_to<BoneAttachment3D>(p_current); - _convert_bone_attachment_to_gltf(bone, state, p_gltf_parent, p_gltf_root, gltf_node); + _convert_bone_attachment_to_gltf(bone, p_state, p_gltf_parent, p_gltf_root, gltf_node); return; } else if (cast_to<Skeleton3D>(p_current)) { Skeleton3D *skel = cast_to<Skeleton3D>(p_current); - _convert_skeleton_to_gltf(skel, state, p_gltf_parent, p_gltf_root, gltf_node); + _convert_skeleton_to_gltf(skel, p_state, p_gltf_parent, p_gltf_root, gltf_node); // We ignore the Godot Engine node that is the skeleton. return; } else if (cast_to<MultiMeshInstance3D>(p_current)) { MultiMeshInstance3D *multi = cast_to<MultiMeshInstance3D>(p_current); - _convert_multi_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, state); + _convert_multi_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, p_state); #ifdef MODULE_CSG_ENABLED } else if (cast_to<CSGShape3D>(p_current)) { CSGShape3D *shape = cast_to<CSGShape3D>(p_current); if (shape->get_parent() && shape->is_root_shape()) { - _convert_csg_shape_to_gltf(shape, p_gltf_parent, gltf_node, state); + _convert_csg_shape_to_gltf(shape, p_gltf_parent, gltf_node, p_state); } #endif // MODULE_CSG_ENABLED #ifdef MODULE_GRIDMAP_ENABLED } else if (cast_to<GridMap>(p_current)) { GridMap *gridmap = Object::cast_to<GridMap>(p_current); - _convert_grid_map_to_gltf(gridmap, p_gltf_parent, p_gltf_root, gltf_node, state); + _convert_grid_map_to_gltf(gridmap, p_gltf_parent, p_gltf_root, gltf_node, p_state); #endif // MODULE_GRIDMAP_ENABLED } else if (cast_to<Camera3D>(p_current)) { Camera3D *camera = Object::cast_to<Camera3D>(p_current); - _convert_camera_to_gltf(camera, state, gltf_node); + _convert_camera_to_gltf(camera, p_state, gltf_node); } else if (cast_to<Light3D>(p_current)) { Light3D *light = Object::cast_to<Light3D>(p_current); - _convert_light_to_gltf(light, state, gltf_node); + _convert_light_to_gltf(light, p_state, gltf_node); } else if (cast_to<AnimationPlayer>(p_current)) { AnimationPlayer *animation_player = Object::cast_to<AnimationPlayer>(p_current); - _convert_animation_player_to_gltf(animation_player, state, p_gltf_parent, p_gltf_root, gltf_node, p_current); + _convert_animation_player_to_gltf(animation_player, p_state, p_gltf_parent, p_gltf_root, gltf_node, p_current); } - GLTFNodeIndex current_node_i = state->nodes.size(); + for (Ref<GLTFDocumentExtension> ext : document_extensions) { + ERR_CONTINUE(ext.is_null()); + ext->convert_scene_node(p_state, gltf_node, p_current); + } + GLTFNodeIndex current_node_i = p_state->nodes.size(); GLTFNodeIndex gltf_root = p_gltf_root; if (gltf_root == -1) { gltf_root = current_node_i; Array scenes; scenes.push_back(gltf_root); - state->json["scene"] = scenes; + p_state->json["scene"] = scenes; } - _create_gltf_node(state, p_current, current_node_i, p_gltf_parent, gltf_root, gltf_node); + _create_gltf_node(p_state, p_current, current_node_i, p_gltf_parent, gltf_root, gltf_node); for (int node_i = 0; node_i < p_current->get_child_count(); node_i++) { - _convert_scene_node(state, p_current->get_child(node_i), current_node_i, gltf_root); + _convert_scene_node(p_state, p_current->get_child(node_i), current_node_i, gltf_root); } } #ifdef MODULE_CSG_ENABLED -void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) { +void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) { CSGShape3D *csg = p_current; csg->call("_update_shape"); Array meshes = csg->get_meshes(); @@ -5317,34 +5332,34 @@ void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeInd Ref<GLTFMesh> gltf_mesh; gltf_mesh.instantiate(); gltf_mesh->set_mesh(mesh); - GLTFMeshIndex mesh_i = state->meshes.size(); - state->meshes.push_back(gltf_mesh); - gltf_node->mesh = mesh_i; - gltf_node->xform = csg->get_meshes()[0]; - gltf_node->set_name(_gen_unique_name(state, csg->get_name())); + GLTFMeshIndex mesh_i = p_state->meshes.size(); + p_state->meshes.push_back(gltf_mesh); + p_gltf_node->mesh = mesh_i; + p_gltf_node->xform = csg->get_meshes()[0]; + p_gltf_node->set_name(_gen_unique_name(p_state, csg->get_name())); } #endif // MODULE_CSG_ENABLED -void GLTFDocument::_create_gltf_node(Ref<GLTFState> state, Node *p_scene_parent, GLTFNodeIndex current_node_i, - GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref<GLTFNode> gltf_node) { - state->scene_nodes.insert(current_node_i, p_scene_parent); - state->nodes.push_back(gltf_node); - ERR_FAIL_COND(current_node_i == p_parent_node_index); - state->nodes.write[current_node_i]->parent = p_parent_node_index; +void GLTFDocument::_create_gltf_node(Ref<GLTFState> p_state, Node *p_scene_parent, GLTFNodeIndex p_current_node_i, + GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref<GLTFNode> p_gltf_node) { + p_state->scene_nodes.insert(p_current_node_i, p_scene_parent); + p_state->nodes.push_back(p_gltf_node); + ERR_FAIL_COND(p_current_node_i == p_parent_node_index); + p_state->nodes.write[p_current_node_i]->parent = p_parent_node_index; if (p_parent_node_index == -1) { return; } - state->nodes.write[p_parent_node_index]->children.push_back(current_node_i); + p_state->nodes.write[p_parent_node_index]->children.push_back(p_current_node_i); } -void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *animation_player, Ref<GLTFState> state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) { - ERR_FAIL_COND(!animation_player); - state->animation_players.push_back(animation_player); - print_verbose(String("glTF: Converting animation player: ") + animation_player->get_name()); +void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *p_animation_player, Ref<GLTFState> p_state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) { + ERR_FAIL_COND(!p_animation_player); + p_state->animation_players.push_back(p_animation_player); + print_verbose(String("glTF: Converting animation player: ") + p_animation_player->get_name()); } -void GLTFDocument::_check_visibility(Node *p_node, bool &retflag) { - retflag = true; +void GLTFDocument::_check_visibility(Node *p_node, bool &r_retflag) { + r_retflag = true; Node3D *spatial = Object::cast_to<Node3D>(p_node); Node2D *node_2d = Object::cast_to<Node2D>(p_node); if (node_2d && !node_2d->is_visible()) { @@ -5353,32 +5368,32 @@ void GLTFDocument::_check_visibility(Node *p_node, bool &retflag) { if (spatial && !spatial->is_visible()) { return; } - retflag = false; + r_retflag = false; } -void GLTFDocument::_convert_camera_to_gltf(Camera3D *camera, Ref<GLTFState> state, Ref<GLTFNode> gltf_node) { +void GLTFDocument::_convert_camera_to_gltf(Camera3D *camera, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) { ERR_FAIL_COND(!camera); - GLTFCameraIndex camera_index = _convert_camera(state, camera); + GLTFCameraIndex camera_index = _convert_camera(p_state, camera); if (camera_index != -1) { - gltf_node->camera = camera_index; + p_gltf_node->camera = camera_index; } } -void GLTFDocument::_convert_light_to_gltf(Light3D *light, Ref<GLTFState> state, Ref<GLTFNode> gltf_node) { +void GLTFDocument::_convert_light_to_gltf(Light3D *light, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) { ERR_FAIL_COND(!light); - GLTFLightIndex light_index = _convert_light(state, light); + GLTFLightIndex light_index = _convert_light(p_state, light); if (light_index != -1) { - gltf_node->light = light_index; + p_gltf_node->light = light_index; } } #ifdef MODULE_GRIDMAP_ENABLED -void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) { +void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) { Array cells = p_grid_map->get_used_cells(); for (int32_t k = 0; k < cells.size(); k++) { GLTFNode *new_gltf_node = memnew(GLTFNode); - gltf_node->children.push_back(state->nodes.size()); - state->nodes.push_back(new_gltf_node); + p_gltf_node->children.push_back(p_state->nodes.size()); + p_state->nodes.push_back(new_gltf_node); Vector3 cell_location = cells[k]; int32_t cell = p_grid_map->get_cell_item( Vector3(cell_location.x, cell_location.y, cell_location.z)); @@ -5394,10 +5409,10 @@ void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex Ref<GLTFMesh> gltf_mesh; gltf_mesh.instantiate(); gltf_mesh->set_mesh(_mesh_to_importer_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell))); - new_gltf_node->mesh = state->meshes.size(); - state->meshes.push_back(gltf_mesh); + new_gltf_node->mesh = p_state->meshes.size(); + p_state->meshes.push_back(gltf_mesh); new_gltf_node->xform = cell_xform * p_grid_map->get_transform(); - new_gltf_node->set_name(_gen_unique_name(state, p_grid_map->get_mesh_library()->get_item_name(cell))); + new_gltf_node->set_name(_gen_unique_name(p_state, p_grid_map->get_mesh_library()->get_item_name(cell))); } } #endif // MODULE_GRIDMAP_ENABLED @@ -5406,7 +5421,7 @@ void GLTFDocument::_convert_multi_mesh_instance_to_gltf( MultiMeshInstance3D *p_multi_mesh_instance, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, - Ref<GLTFNode> gltf_node, Ref<GLTFState> state) { + Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state) { ERR_FAIL_COND(!p_multi_mesh_instance); Ref<MultiMesh> multi_mesh = p_multi_mesh_instance->get_multimesh(); if (multi_mesh.is_null()) { @@ -5442,8 +5457,8 @@ void GLTFDocument::_convert_multi_mesh_instance_to_gltf( blend_arrays, mesh->surface_get_lods(surface_i), mat, material_name, mesh->surface_get_format(surface_i)); } gltf_mesh->set_mesh(importer_mesh); - GLTFMeshIndex mesh_index = state->meshes.size(); - state->meshes.push_back(gltf_mesh); + GLTFMeshIndex mesh_index = p_state->meshes.size(); + p_state->meshes.push_back(gltf_mesh); for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count(); instance_i++) { Transform3D transform; @@ -5465,22 +5480,22 @@ void GLTFDocument::_convert_multi_mesh_instance_to_gltf( new_gltf_node.instantiate(); new_gltf_node->mesh = mesh_index; new_gltf_node->xform = transform; - new_gltf_node->set_name(_gen_unique_name(state, p_multi_mesh_instance->get_name())); - gltf_node->children.push_back(state->nodes.size()); - state->nodes.push_back(new_gltf_node); + new_gltf_node->set_name(_gen_unique_name(p_state, p_multi_mesh_instance->get_name())); + p_gltf_node->children.push_back(p_state->nodes.size()); + p_state->nodes.push_back(new_gltf_node); } } -void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFState> state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node) { +void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFState> p_state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node) { Skeleton3D *skeleton = p_skeleton3d; Ref<GLTFSkeleton> gltf_skeleton; gltf_skeleton.instantiate(); - // GLTFSkeleton is only used to hold internal state data. It will not be written to the document. + // GLTFSkeleton is only used to hold internal p_state data. It will not be written to the document. // gltf_skeleton->godot_skeleton = skeleton; - GLTFSkeletonIndex skeleton_i = state->skeletons.size(); - state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skeleton_i; - state->skeletons.push_back(gltf_skeleton); + GLTFSkeletonIndex skeleton_i = p_state->skeletons.size(); + p_state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()] = skeleton_i; + p_state->skeletons.push_back(gltf_skeleton); BoneId bone_count = skeleton->get_bone_count(); for (BoneId bone_i = 0; bone_i < bone_count; bone_i++) { @@ -5488,15 +5503,15 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFS joint_node.instantiate(); // Note that we cannot use _gen_unique_bone_name here, because glTF spec requires all node // names to be unique regardless of whether or not they are used as joints. - joint_node->set_name(_gen_unique_name(state, skeleton->get_bone_name(bone_i))); + joint_node->set_name(_gen_unique_name(p_state, skeleton->get_bone_name(bone_i))); Transform3D xform = skeleton->get_bone_pose(bone_i); joint_node->scale = xform.basis.get_scale(); joint_node->rotation = xform.basis.get_rotation_quaternion(); joint_node->position = xform.origin; joint_node->joint = true; - GLTFNodeIndex current_node_i = state->nodes.size(); - state->scene_nodes.insert(current_node_i, skeleton); - state->nodes.push_back(joint_node); + GLTFNodeIndex current_node_i = p_state->nodes.size(); + p_state->scene_nodes.insert(current_node_i, skeleton); + p_state->nodes.push_back(joint_node); gltf_skeleton->joints.push_back(current_node_i); if (skeleton->get_bone_parent(bone_i) == -1) { @@ -5509,23 +5524,23 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFS BoneId parent_bone_id = skeleton->get_bone_parent(bone_i); if (parent_bone_id == -1) { if (p_parent_node_index != -1) { - state->nodes.write[current_node_i]->parent = p_parent_node_index; - state->nodes.write[p_parent_node_index]->children.push_back(current_node_i); + p_state->nodes.write[current_node_i]->parent = p_parent_node_index; + p_state->nodes.write[p_parent_node_index]->children.push_back(current_node_i); } } else { GLTFNodeIndex parent_node_i = gltf_skeleton->godot_bone_node[parent_bone_id]; - state->nodes.write[current_node_i]->parent = parent_node_i; - state->nodes.write[parent_node_i]->children.push_back(current_node_i); + p_state->nodes.write[current_node_i]->parent = parent_node_i; + p_state->nodes.write[parent_node_i]->children.push_back(current_node_i); } } // Remove placeholder skeleton3d node by not creating the gltf node // Skins are per mesh for (int node_i = 0; node_i < skeleton->get_child_count(); node_i++) { - _convert_scene_node(state, skeleton->get_child(node_i), p_parent_node_index, p_root_node_index); + _convert_scene_node(p_state, skeleton->get_child(node_i), p_parent_node_index, p_root_node_index); } } -void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_attachment, Ref<GLTFState> state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node) { +void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_attachment, Ref<GLTFState> p_state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> p_gltf_node) { Skeleton3D *skeleton; // Note that relative transforms to external skeletons and pose overrides are not supported. if (p_bone_attachment->get_use_external_skeleton()) { @@ -5534,8 +5549,8 @@ void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_att skeleton = cast_to<Skeleton3D>(p_bone_attachment->get_parent()); } GLTFSkeletonIndex skel_gltf_i = -1; - if (skeleton != nullptr && state->skeleton3d_to_gltf_skeleton.has(skeleton->get_instance_id())) { - skel_gltf_i = state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()]; + if (skeleton != nullptr && p_state->skeleton3d_to_gltf_skeleton.has(skeleton->get_instance_id())) { + skel_gltf_i = p_state->skeleton3d_to_gltf_skeleton[skeleton->get_instance_id()]; } int bone_idx = -1; if (skeleton != nullptr) { @@ -5546,28 +5561,28 @@ void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_att } GLTFNodeIndex par_node_index = p_parent_node_index; if (skeleton != nullptr && bone_idx != -1 && skel_gltf_i != -1) { - Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_gltf_i]; + Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_gltf_i]; gltf_skeleton->bone_attachments.push_back(p_bone_attachment); par_node_index = gltf_skeleton->joints[bone_idx]; } for (int node_i = 0; node_i < p_bone_attachment->get_child_count(); node_i++) { - _convert_scene_node(state, p_bone_attachment->get_child(node_i), par_node_index, p_root_node_index); + _convert_scene_node(p_state, p_bone_attachment->get_child(node_i), par_node_index, p_root_node_index); } } -void GLTFDocument::_convert_mesh_instance_to_gltf(MeshInstance3D *p_scene_parent, Ref<GLTFState> state, Ref<GLTFNode> gltf_node) { - GLTFMeshIndex gltf_mesh_index = _convert_mesh_to_gltf(state, p_scene_parent); +void GLTFDocument::_convert_mesh_instance_to_gltf(MeshInstance3D *p_scene_parent, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) { + GLTFMeshIndex gltf_mesh_index = _convert_mesh_to_gltf(p_state, p_scene_parent); if (gltf_mesh_index != -1) { - gltf_node->mesh = gltf_mesh_index; + p_gltf_node->mesh = gltf_mesh_index; } } -void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) { - Ref<GLTFNode> gltf_node = state->nodes[node_index]; +void GLTFDocument::_generate_scene_node(Ref<GLTFState> p_state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) { + Ref<GLTFNode> gltf_node = p_state->nodes[node_index]; if (gltf_node->skeleton >= 0) { - _generate_skeleton_bone_node(state, scene_parent, scene_root, node_index); + _generate_skeleton_bone_node(p_state, scene_parent, scene_root, node_index); return; } @@ -5581,76 +5596,87 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent // skinned meshes must not be placed in a bone attachment. if (non_bone_parented_to_skeleton && gltf_node->skin < 0) { // Bone Attachment - Parent Case - BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent); + BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, node_index, gltf_node->parent); scene_parent->add_child(bone_attachment, true); bone_attachment->set_owner(scene_root); // There is no gltf_node that represent this, so just directly create a unique name - bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D")); + bone_attachment->set_name(_gen_unique_name(p_state, "BoneAttachment3D")); // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node // and attach it to the bone_attachment scene_parent = bone_attachment; } - if (gltf_node->mesh >= 0) { - current_node = _generate_mesh_instance(state, node_index); - } else if (gltf_node->camera >= 0) { - current_node = _generate_camera(state, node_index); - } else if (gltf_node->light >= 0) { - current_node = _generate_light(state, node_index); + // Check if any GLTFDocumentExtension classes want to generate a node for us. + for (Ref<GLTFDocumentExtension> ext : document_extensions) { + ERR_CONTINUE(ext.is_null()); + current_node = ext->generate_scene_node(p_state, gltf_node, scene_parent); + if (current_node) { + break; + } } - - // We still have not managed to make a node. + // If none of our GLTFDocumentExtension classes generated us a node, we generate one. if (!current_node) { - current_node = _generate_spatial(state, node_index); + if (gltf_node->mesh >= 0) { + current_node = _generate_mesh_instance(p_state, node_index); + } else if (gltf_node->camera >= 0) { + current_node = _generate_camera(p_state, node_index); + } else if (gltf_node->light >= 0) { + current_node = _generate_light(p_state, node_index); + } else { + current_node = _generate_spatial(p_state, node_index); + } } + // Add the node we generated and set the owner to the scene root. scene_parent->add_child(current_node, true); if (current_node != scene_root) { - current_node->set_owner(scene_root); + Array args; + args.append(scene_root); + current_node->propagate_call(StringName("set_owner"), args); } current_node->set_transform(gltf_node->xform); current_node->set_name(gltf_node->get_name()); - state->scene_nodes.insert(node_index, current_node); + p_state->scene_nodes.insert(node_index, current_node); for (int i = 0; i < gltf_node->children.size(); ++i) { - _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]); + _generate_scene_node(p_state, current_node, scene_root, gltf_node->children[i]); } } -void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) { - Ref<GLTFNode> gltf_node = state->nodes[node_index]; +void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, Node *p_scene_parent, Node3D *p_scene_root, const GLTFNodeIndex p_node_index) { + Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index]; Node3D *current_node = nullptr; - Skeleton3D *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton; + Skeleton3D *skeleton = p_state->skeletons[gltf_node->skeleton]->godot_skeleton; // In this case, this node is already a bone in skeleton. const bool is_skinned_mesh = (gltf_node->skin >= 0 && gltf_node->mesh >= 0); const bool requires_extra_node = (gltf_node->mesh >= 0 || gltf_node->camera >= 0 || gltf_node->light >= 0); - Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(scene_parent); + Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(p_scene_parent); if (active_skeleton != skeleton) { if (active_skeleton) { // Bone Attachment - Direct Parented Skeleton Case - BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent); + BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, gltf_node->parent); - scene_parent->add_child(bone_attachment, true); - bone_attachment->set_owner(scene_root); + p_scene_parent->add_child(bone_attachment, true); + bone_attachment->set_owner(p_scene_root); // There is no gltf_node that represent this, so just directly create a unique name - bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D")); + bone_attachment->set_name(_gen_unique_name(p_state, "BoneAttachment3D")); // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node // and attach it to the bone_attachment - scene_parent = bone_attachment; - WARN_PRINT(vformat("glTF: Generating scene detected direct parented Skeletons at node %d", node_index)); + p_scene_parent = bone_attachment; + WARN_PRINT(vformat("glTF: Generating scene detected direct parented Skeletons at node %d", p_node_index)); } // Add it to the scene if it has not already been added if (skeleton->get_parent() == nullptr) { - scene_parent->add_child(skeleton, true); - skeleton->set_owner(scene_root); + p_scene_parent->add_child(skeleton, true); + skeleton->set_owner(p_scene_root); } } @@ -5661,40 +5687,53 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen // skinned meshes must not be placed in a bone attachment. if (!is_skinned_mesh) { // Bone Attachment - Same Node Case - BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, node_index); + BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, p_node_index); - scene_parent->add_child(bone_attachment, true); - bone_attachment->set_owner(scene_root); + p_scene_parent->add_child(bone_attachment, true); + bone_attachment->set_owner(p_scene_root); // There is no gltf_node that represent this, so just directly create a unique name - bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D")); + bone_attachment->set_name(_gen_unique_name(p_state, "BoneAttachment3D")); // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node // and attach it to the bone_attachment - scene_parent = bone_attachment; + p_scene_parent = bone_attachment; } - - // We still have not managed to make a node - if (gltf_node->mesh >= 0) { - current_node = _generate_mesh_instance(state, node_index); - } else if (gltf_node->camera >= 0) { - current_node = _generate_camera(state, node_index); - } else if (gltf_node->light >= 0) { - current_node = _generate_light(state, node_index); + // Check if any GLTFDocumentExtension classes want to generate a node for us. + for (Ref<GLTFDocumentExtension> ext : document_extensions) { + ERR_CONTINUE(ext.is_null()); + current_node = ext->generate_scene_node(p_state, gltf_node, p_scene_parent); + if (current_node) { + break; + } + } + // If none of our GLTFDocumentExtension classes generated us a node, we generate one. + if (!current_node) { + if (gltf_node->mesh >= 0) { + current_node = _generate_mesh_instance(p_state, p_node_index); + } else if (gltf_node->camera >= 0) { + current_node = _generate_camera(p_state, p_node_index); + } else if (gltf_node->light >= 0) { + current_node = _generate_light(p_state, p_node_index); + } else { + current_node = _generate_spatial(p_state, p_node_index); + } } - - scene_parent->add_child(current_node, true); - if (current_node != scene_root) { - current_node->set_owner(scene_root); + // Add the node we generated and set the owner to the scene root. + p_scene_parent->add_child(current_node, true); + if (current_node != p_scene_root) { + Array args; + args.append(p_scene_root); + current_node->propagate_call(StringName("set_owner"), args); } // Do not set transform here. Transform is already applied to our bone. current_node->set_name(gltf_node->get_name()); } - state->scene_nodes.insert(node_index, current_node); + p_state->scene_nodes.insert(p_node_index, current_node); for (int i = 0; i < gltf_node->children.size(); ++i) { - _generate_scene_node(state, active_skeleton, scene_root, gltf_node->children[i]); + _generate_scene_node(p_state, active_skeleton, p_scene_root, gltf_node->children[i]); } } @@ -5819,13 +5858,13 @@ T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T ERR_FAIL_V(p_values[0]); } -void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps) { - Ref<GLTFAnimation> anim = state->animations[index]; +void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const GLTFAnimationIndex p_index, const float p_bake_fps, const bool p_trimming) { + Ref<GLTFAnimation> anim = p_state->animations[p_index]; String anim_name = anim->get_name(); if (anim_name.is_empty()) { // No node represent these, and they are not in the hierarchy, so just make a unique name - anim_name = _gen_unique_name(state, "Animation"); + anim_name = _gen_unique_name(p_state, "Animation"); } Ref<Animation> animation; @@ -5836,7 +5875,8 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, animation->set_loop_mode(Animation::LOOP_LINEAR); } - float length = 0.0; + double anim_start = p_trimming ? INFINITY : 0.0; + double anim_end = 0.0; for (const KeyValue<int, GLTFAnimation::Track> &track_i : anim->get_tracks()) { const GLTFAnimation::Track &track = track_i.value; @@ -5847,38 +5887,59 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, GLTFNodeIndex node_index = track_i.key; - const Ref<GLTFNode> gltf_node = state->nodes[track_i.key]; + const Ref<GLTFNode> gltf_node = p_state->nodes[track_i.key]; - Node *root = ap->get_parent(); + Node *root = p_animation_player->get_parent(); ERR_FAIL_COND(root == nullptr); - HashMap<GLTFNodeIndex, Node *>::Iterator node_element = state->scene_nodes.find(node_index); + HashMap<GLTFNodeIndex, Node *>::Iterator node_element = p_state->scene_nodes.find(node_index); ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation", node_index)); node_path = root->get_path_to(node_element->value); if (gltf_node->skeleton >= 0) { - const Skeleton3D *sk = state->skeletons[gltf_node->skeleton]->godot_skeleton; + const Skeleton3D *sk = p_state->skeletons[gltf_node->skeleton]->godot_skeleton; ERR_FAIL_COND(sk == nullptr); - const String path = ap->get_parent()->get_path_to(sk); + const String path = p_animation_player->get_parent()->get_path_to(sk); const String bone = gltf_node->get_name(); transform_node_path = path + ":" + bone; } else { transform_node_path = node_path; } - for (int i = 0; i < track.rotation_track.times.size(); i++) { - length = MAX(length, track.rotation_track.times[i]); - } - for (int i = 0; i < track.position_track.times.size(); i++) { - length = MAX(length, track.position_track.times[i]); - } - for (int i = 0; i < track.scale_track.times.size(); i++) { - length = MAX(length, track.scale_track.times[i]); - } - - for (int i = 0; i < track.weight_tracks.size(); i++) { - for (int j = 0; j < track.weight_tracks[i].times.size(); j++) { - length = MAX(length, track.weight_tracks[i].times[j]); + if (p_trimming) { + for (int i = 0; i < track.rotation_track.times.size(); i++) { + anim_start = MIN(anim_start, track.rotation_track.times[i]); + anim_end = MAX(anim_end, track.rotation_track.times[i]); + } + for (int i = 0; i < track.position_track.times.size(); i++) { + anim_start = MIN(anim_start, track.position_track.times[i]); + anim_end = MAX(anim_end, track.position_track.times[i]); + } + for (int i = 0; i < track.scale_track.times.size(); i++) { + anim_start = MIN(anim_start, track.scale_track.times[i]); + anim_end = MAX(anim_end, track.scale_track.times[i]); + } + for (int i = 0; i < track.weight_tracks.size(); i++) { + for (int j = 0; j < track.weight_tracks[i].times.size(); j++) { + anim_start = MIN(anim_start, track.weight_tracks[i].times[j]); + anim_end = MAX(anim_end, track.weight_tracks[i].times[j]); + } + } + } else { + // If you don't use trimming and the first key time is not at 0.0, fake keys will be inserted. + for (int i = 0; i < track.rotation_track.times.size(); i++) { + anim_end = MAX(anim_end, track.rotation_track.times[i]); + } + for (int i = 0; i < track.position_track.times.size(); i++) { + anim_end = MAX(anim_end, track.position_track.times[i]); + } + for (int i = 0; i < track.scale_track.times.size(); i++) { + anim_end = MAX(anim_end, track.scale_track.times[i]); + } + for (int i = 0; i < track.weight_tracks.size(); i++) { + for (int j = 0; j < track.weight_tracks[i].times.size(); j++) { + anim_end = MAX(anim_end, track.weight_tracks[i].times[j]); + } } } @@ -5892,7 +5953,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, int scale_idx = -1; if (track.position_track.values.size()) { - Vector3 base_pos = state->nodes[track_i.key]->position; + Vector3 base_pos = p_state->nodes[track_i.key]->position; bool not_default = false; //discard the track if all it contains is default values for (int i = 0; i < track.position_track.times.size(); i++) { Vector3 value = track.position_track.values[track.position_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i]; @@ -5911,7 +5972,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, } } if (track.rotation_track.values.size()) { - Quaternion base_rot = state->nodes[track_i.key]->rotation.normalized(); + Quaternion base_rot = p_state->nodes[track_i.key]->rotation.normalized(); bool not_default = false; //discard the track if all it contains is default values for (int i = 0; i < track.rotation_track.times.size(); i++) { Quaternion value = track.rotation_track.values[track.rotation_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i].normalized(); @@ -5929,7 +5990,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, } } if (track.scale_track.values.size()) { - Vector3 base_scale = state->nodes[track_i.key]->scale; + Vector3 base_scale = p_state->nodes[track_i.key]->scale; bool not_default = false; //discard the track if all it contains is default values for (int i = 0; i < track.scale_track.times.size(); i++) { Vector3 value = track.scale_track.values[track.scale_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i]; @@ -5947,25 +6008,23 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, } } - //first determine animation length - - const double increment = 1.0 / bake_fps; - double time = 0.0; + const double increment = 1.0 / p_bake_fps; + double time = anim_start; Vector3 base_pos; Quaternion base_rot; Vector3 base_scale = Vector3(1, 1, 1); if (rotation_idx == -1) { - base_rot = state->nodes[track_i.key]->rotation.normalized(); + base_rot = p_state->nodes[track_i.key]->rotation.normalized(); } if (position_idx == -1) { - base_pos = state->nodes[track_i.key]->position; + base_pos = p_state->nodes[track_i.key]->position; } if (scale_idx == -1) { - base_scale = state->nodes[track_i.key]->scale; + base_scale = p_state->nodes[track_i.key]->scale; } bool last = false; @@ -5976,33 +6035,33 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, if (position_idx >= 0) { pos = _interpolate_track<Vector3>(track.position_track.times, track.position_track.values, time, track.position_track.interpolation); - animation->position_track_insert_key(position_idx, time, pos); + animation->position_track_insert_key(position_idx, time - anim_start, pos); } if (rotation_idx >= 0) { rot = _interpolate_track<Quaternion>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation); - animation->rotation_track_insert_key(rotation_idx, time, rot); + animation->rotation_track_insert_key(rotation_idx, time - anim_start, rot); } if (scale_idx >= 0) { scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation); - animation->scale_track_insert_key(scale_idx, time, scale); + animation->scale_track_insert_key(scale_idx, time - anim_start, scale); } if (last) { break; } time += increment; - if (time >= length) { + if (time >= anim_end) { last = true; - time = length; + time = anim_end; } } } for (int i = 0; i < track.weight_tracks.size(); i++) { - ERR_CONTINUE(gltf_node->mesh < 0 || gltf_node->mesh >= state->meshes.size()); - Ref<GLTFMesh> mesh = state->meshes[gltf_node->mesh]; + ERR_CONTINUE(gltf_node->mesh < 0 || gltf_node->mesh >= p_state->meshes.size()); + Ref<GLTFMesh> mesh = p_state->meshes[gltf_node->mesh]; ERR_CONTINUE(mesh.is_null()); ERR_CONTINUE(mesh->get_mesh().is_null()); ERR_CONTINUE(mesh->get_mesh()->get_mesh().is_null()); @@ -6025,45 +6084,45 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, } } else { // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. - const double increment = 1.0 / bake_fps; + const double increment = 1.0 / p_bake_fps; double time = 0.0; bool last = false; while (true) { real_t blend = _interpolate_track<real_t>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp); - animation->blend_shape_track_insert_key(track_idx, time, blend); + animation->blend_shape_track_insert_key(track_idx, time - anim_start, blend); if (last) { break; } time += increment; - if (time >= length) { + if (time >= anim_end) { last = true; - time = length; + time = anim_end; } } } } } - animation->set_length(length); + animation->set_length(anim_end - anim_start); Ref<AnimationLibrary> library; - if (!ap->has_animation_library("")) { + if (!p_animation_player->has_animation_library("")) { library.instantiate(); - ap->add_animation_library("", library); + p_animation_player->add_animation_library("", library); } else { - library = ap->get_animation_library(""); + library = p_animation_player->get_animation_library(""); } library->add_animation(anim_name, animation); } -void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) { - for (GLTFNodeIndex mi_node_i = 0; mi_node_i < state->nodes.size(); ++mi_node_i) { - Ref<GLTFNode> node = state->nodes[mi_node_i]; +void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> p_state) { + for (GLTFNodeIndex mi_node_i = 0; mi_node_i < p_state->nodes.size(); ++mi_node_i) { + Ref<GLTFNode> node = p_state->nodes[mi_node_i]; if (node->mesh < 0) { continue; } - HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = state->scene_nodes.find(mi_node_i); + HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = p_state->scene_nodes.find(mi_node_i); if (!mi_element) { continue; } @@ -6094,10 +6153,10 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) { if (skel_node != nullptr) { godot_skeleton = cast_to<Skeleton3D>(skel_node); } - if (godot_skeleton != nullptr && state->skeleton3d_to_gltf_skeleton.has(godot_skeleton->get_instance_id())) { + if (godot_skeleton != nullptr && p_state->skeleton3d_to_gltf_skeleton.has(godot_skeleton->get_instance_id())) { // This is a skinned mesh. If the mesh has no ARRAY_WEIGHTS or ARRAY_BONES, it will be invisible. - const GLTFSkeletonIndex skeleton_gltf_i = state->skeleton3d_to_gltf_skeleton[godot_skeleton->get_instance_id()]; - Ref<GLTFSkeleton> gltf_skeleton = state->skeletons[skeleton_gltf_i]; + const GLTFSkeletonIndex skeleton_gltf_i = p_state->skeleton3d_to_gltf_skeleton[godot_skeleton->get_instance_id()]; + Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons[skeleton_gltf_i]; int bone_cnt = skeleton->get_bone_count(); ERR_FAIL_COND(bone_cnt != gltf_skeleton->joints.size()); @@ -6111,8 +6170,8 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) { if (!gltf_skeleton->roots.is_empty()) { root_gltf_i = gltf_skeleton->roots[0]; } - if (state->skin_and_skeleton3d_to_gltf_skin.has(gltf_skin_key) && state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key].has(gltf_skel_key)) { - skin_gltf_i = state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key]; + if (p_state->skin_and_skeleton3d_to_gltf_skin.has(gltf_skin_key) && p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key].has(gltf_skel_key)) { + skin_gltf_i = p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key]; } else { if (skin.is_null()) { // Note that gltf_skin_key should remain null, so these can share a reference. @@ -6149,9 +6208,9 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) { gltf_skin->joint_i_to_bone_i[bind_i] = bone_i; gltf_skin->joint_i_to_name[bind_i] = bind_name; } - skin_gltf_i = state->skins.size(); - state->skins.push_back(gltf_skin); - state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key] = skin_gltf_i; + skin_gltf_i = p_state->skins.size(); + p_state->skins.push_back(gltf_skin); + p_state->skin_and_skeleton3d_to_gltf_skin[gltf_skin_key][gltf_skel_key] = skin_gltf_i; } node->skin = skin_gltf_i; node->skeleton = skeleton_gltf_i; @@ -6159,14 +6218,14 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) { } } -float GLTFDocument::solve_metallic(float p_dielectric_specular, float diffuse, float specular, float p_one_minus_specular_strength) { - if (specular <= p_dielectric_specular) { +float GLTFDocument::solve_metallic(float p_dielectric_specular, float p_diffuse, float p_specular, float p_one_minus_specular_strength) { + if (p_specular <= p_dielectric_specular) { return 0.0f; } const float a = p_dielectric_specular; - const float b = diffuse * p_one_minus_specular_strength / (1.0f - p_dielectric_specular) + specular - 2.0f * p_dielectric_specular; - const float c = p_dielectric_specular - specular; + const float b = p_diffuse * p_one_minus_specular_strength / (1.0f - p_dielectric_specular) + p_specular - 2.0f * p_dielectric_specular; + const float c = p_dielectric_specular - p_specular; const float D = b * b - 4.0f * a * c; return CLAMP((-b + Math::sqrt(D)) / (2.0f * a), 0.0f, 1.0f); } @@ -6190,21 +6249,21 @@ float GLTFDocument::get_max_component(const Color &p_color) { return MAX(MAX(r, g), b); } -void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_root) { - for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); ++node_i) { - Ref<GLTFNode> node = state->nodes[node_i]; +void GLTFDocument::_process_mesh_instances(Ref<GLTFState> p_state, Node *p_scene_root) { + for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); ++node_i) { + Ref<GLTFNode> node = p_state->nodes[node_i]; if (node->skin >= 0 && node->mesh >= 0) { const GLTFSkinIndex skin_i = node->skin; - HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = state->scene_nodes.find(node_i); + HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = p_state->scene_nodes.find(node_i); ERR_CONTINUE_MSG(!mi_element, vformat("Unable to find node %d", node_i)); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(mi_element->value); ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, mi_element->value->get_class_name())); - const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton; - Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i]; + const GLTFSkeletonIndex skel_i = p_state->skins.write[node->skin]->skeleton; + Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_i]; Skeleton3D *skeleton = gltf_skeleton->godot_skeleton; ERR_CONTINUE_MSG(skeleton == nullptr, vformat("Unable to find Skeleton for node %d skin %d", node_i, skin_i)); @@ -6212,14 +6271,14 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo skeleton->add_child(mi, true); mi->set_owner(skeleton->get_owner()); - mi->set_skin(state->skins.write[skin_i]->godot_skin); + mi->set_skin(p_state->skins.write[skin_i]->godot_skin); mi->set_skeleton_path(mi->get_path_to(skeleton)); mi->set_transform(Transform3D()); } } } -GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, int32_t p_track_i, GLTFNodeIndex p_node_i) { +GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, int32_t p_track_i, GLTFNodeIndex p_node_i) { Animation::InterpolationType interpolation = p_animation->track_get_interpolation_type(p_track_i); GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::INTERP_LINEAR; @@ -6365,11 +6424,11 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state return p_track; } -void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, String p_animation_track_name) { - Ref<Animation> animation = ap->get_animation(p_animation_track_name); +void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, String p_animation_track_name) { + Ref<Animation> animation = p_animation_player->get_animation(p_animation_track_name); Ref<GLTFAnimation> gltf_animation; gltf_animation.instantiate(); - gltf_animation->set_name(_gen_unique_name(state, p_animation_track_name)); + gltf_animation->set_name(_gen_unique_name(p_state, p_animation_track_name)); for (int32_t track_i = 0; track_i < animation->get_track_count(); track_i++) { if (!animation->track_is_enabled(track_i)) { @@ -6379,8 +6438,8 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, if (String(orig_track_path).contains(":position")) { const Vector<String> node_suffix = String(orig_track_path).split(":position"); const NodePath path = node_suffix[0]; - const Node *node = ap->get_parent()->get_node_or_null(path); - for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : state->scene_nodes) { + const Node *node = p_animation_player->get_parent()->get_node_or_null(path); + for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : p_state->scene_nodes) { if (position_scene_node_i.value == node) { GLTFNodeIndex node_index = position_scene_node_i.key; HashMap<int, GLTFAnimation::Track>::Iterator position_track_i = gltf_animation->get_tracks().find(node_index); @@ -6388,15 +6447,15 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, if (position_track_i) { track = position_track_i->value; } - track = _convert_animation_track(state, track, animation, track_i, node_index); + track = _convert_animation_track(p_state, track, animation, track_i, node_index); gltf_animation->get_tracks().insert(node_index, track); } } } else if (String(orig_track_path).contains(":rotation_degrees")) { const Vector<String> node_suffix = String(orig_track_path).split(":rotation_degrees"); const NodePath path = node_suffix[0]; - const Node *node = ap->get_parent()->get_node_or_null(path); - for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : state->scene_nodes) { + const Node *node = p_animation_player->get_parent()->get_node_or_null(path); + for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : p_state->scene_nodes) { if (rotation_degree_scene_node_i.value == node) { GLTFNodeIndex node_index = rotation_degree_scene_node_i.key; HashMap<int, GLTFAnimation::Track>::Iterator rotation_degree_track_i = gltf_animation->get_tracks().find(node_index); @@ -6404,15 +6463,15 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, if (rotation_degree_track_i) { track = rotation_degree_track_i->value; } - track = _convert_animation_track(state, track, animation, track_i, node_index); + track = _convert_animation_track(p_state, track, animation, track_i, node_index); gltf_animation->get_tracks().insert(node_index, track); } } } else if (String(orig_track_path).contains(":scale")) { const Vector<String> node_suffix = String(orig_track_path).split(":scale"); const NodePath path = node_suffix[0]; - const Node *node = ap->get_parent()->get_node_or_null(path); - for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : state->scene_nodes) { + const Node *node = p_animation_player->get_parent()->get_node_or_null(path); + for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : p_state->scene_nodes) { if (scale_scene_node_i.value == node) { GLTFNodeIndex node_index = scale_scene_node_i.key; HashMap<int, GLTFAnimation::Track>::Iterator scale_track_i = gltf_animation->get_tracks().find(node_index); @@ -6420,18 +6479,18 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, if (scale_track_i) { track = scale_track_i->value; } - track = _convert_animation_track(state, track, animation, track_i, node_index); + track = _convert_animation_track(p_state, track, animation, track_i, node_index); gltf_animation->get_tracks().insert(node_index, track); } } } else if (String(orig_track_path).contains(":transform")) { const Vector<String> node_suffix = String(orig_track_path).split(":transform"); const NodePath path = node_suffix[0]; - const Node *node = ap->get_parent()->get_node_or_null(path); - for (const KeyValue<GLTFNodeIndex, Node *> &transform_track_i : state->scene_nodes) { + const Node *node = p_animation_player->get_parent()->get_node_or_null(path); + for (const KeyValue<GLTFNodeIndex, Node *> &transform_track_i : p_state->scene_nodes) { if (transform_track_i.value == node) { GLTFAnimation::Track track; - track = _convert_animation_track(state, track, animation, track_i, transform_track_i.key); + track = _convert_animation_track(p_state, track, animation, track_i, transform_track_i.key); gltf_animation->get_tracks().insert(transform_track_i.key, track); } } @@ -6439,12 +6498,12 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, const Vector<String> node_suffix = String(orig_track_path).split(":"); const NodePath path = node_suffix[0]; const String suffix = node_suffix[1]; - Node *node = ap->get_parent()->get_node_or_null(path); + Node *node = p_animation_player->get_parent()->get_node_or_null(path); MeshInstance3D *mi = cast_to<MeshInstance3D>(node); Ref<Mesh> mesh = mi->get_mesh(); ERR_CONTINUE(mesh.is_null()); int32_t mesh_index = -1; - for (const KeyValue<GLTFNodeIndex, Node *> &mesh_track_i : state->scene_nodes) { + for (const KeyValue<GLTFNodeIndex, Node *> &mesh_track_i : p_state->scene_nodes) { if (mesh_track_i.value == node) { mesh_index = mesh_track_i.key; } @@ -6497,15 +6556,15 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, const String node = node_suffix[0]; const NodePath node_path = node; const String suffix = node_suffix[1]; - Node *godot_node = ap->get_parent()->get_node_or_null(node_path); + Node *godot_node = p_animation_player->get_parent()->get_node_or_null(node_path); Skeleton3D *skeleton = nullptr; GLTFSkeletonIndex skeleton_gltf_i = -1; - for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < state->skeletons.size(); skeleton_i++) { - if (state->skeletons[skeleton_i]->godot_skeleton == cast_to<Skeleton3D>(godot_node)) { - skeleton = state->skeletons[skeleton_i]->godot_skeleton; + for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < p_state->skeletons.size(); skeleton_i++) { + if (p_state->skeletons[skeleton_i]->godot_skeleton == cast_to<Skeleton3D>(godot_node)) { + skeleton = p_state->skeletons[skeleton_i]->godot_skeleton; skeleton_gltf_i = skeleton_i; ERR_CONTINUE(!skeleton); - Ref<GLTFSkeleton> skeleton_gltf = state->skeletons[skeleton_gltf_i]; + Ref<GLTFSkeleton> skeleton_gltf = p_state->skeletons[skeleton_gltf_i]; int32_t bone = skeleton->find_bone(suffix); ERR_CONTINUE(bone == -1); if (!skeleton_gltf->godot_bone_node.has(bone)) { @@ -6517,14 +6576,14 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, if (property_track_i) { track = property_track_i->value; } - track = _convert_animation_track(state, track, animation, track_i, node_i); + track = _convert_animation_track(p_state, track, animation, track_i, node_i); gltf_animation->get_tracks()[node_i] = track; } } } else if (!String(orig_track_path).contains(":")) { - ERR_CONTINUE(!ap->get_parent()); - Node *godot_node = ap->get_parent()->get_node_or_null(orig_track_path); - for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : state->scene_nodes) { + ERR_CONTINUE(!p_animation_player->get_parent()); + Node *godot_node = p_animation_player->get_parent()->get_node_or_null(orig_track_path); + for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : p_state->scene_nodes) { if (scene_node_i.value == godot_node) { GLTFNodeIndex node_i = scene_node_i.key; HashMap<int, GLTFAnimation::Track>::Iterator node_track_i = gltf_animation->get_tracks().find(node_i); @@ -6532,7 +6591,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, if (node_track_i) { track = node_track_i->value; } - track = _convert_animation_track(state, track, animation, track_i, node_i); + track = _convert_animation_track(p_state, track, animation, track_i, node_i); gltf_animation->get_tracks()[node_i] = track; break; } @@ -6540,42 +6599,42 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, } } if (gltf_animation->get_tracks().size()) { - state->animations.push_back(gltf_animation); + p_state->animations.push_back(gltf_animation); } } -Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> f, int p_bake_fps) { +Error GLTFDocument::_parse(Ref<GLTFState> p_state, String p_path, Ref<FileAccess> p_file) { Error err; - if (f.is_null()) { + if (p_file.is_null()) { return FAILED; } - f->seek(0); - uint32_t magic = f->get_32(); + p_file->seek(0); + uint32_t magic = p_file->get_32(); if (magic == 0x46546C67) { //binary file //text file - f->seek(0); - err = _parse_glb(f, state); + p_file->seek(0); + err = _parse_glb(p_file, p_state); if (err != OK) { return err; } } else { - f->seek(0); - String text = f->get_as_utf8_string(); + p_file->seek(0); + String text = p_file->get_as_utf8_string(); JSON json; err = json.parse(text); if (err != OK) { _err_print_error("", "", json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT); } ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - state->json = json.get_data(); + p_state->json = json.get_data(); } - if (!state->json.has("asset")) { + if (!p_state->json.has("asset")) { return ERR_PARSE_ERROR; } - Dictionary asset = state->json["asset"]; + Dictionary asset = p_state->json["asset"]; if (!asset.has("version")) { return ERR_PARSE_ERROR; @@ -6583,17 +6642,19 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> String version = asset["version"]; - state->major_version = version.get_slice(".", 0).to_int(); - state->minor_version = version.get_slice(".", 1).to_int(); + p_state->major_version = version.get_slice(".", 0).to_int(); + p_state->minor_version = version.get_slice(".", 1).to_int(); - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + document_extensions.clear(); + for (Ref<GLTFDocumentExtension> ext : all_document_extensions) { ERR_CONTINUE(ext.is_null()); - err = ext->import_preflight(state); - ERR_FAIL_COND_V(err != OK, err); + err = ext->import_preflight(p_state, p_state->json["extensionsUsed"]); + if (err == OK) { + document_extensions.push_back(ext); + } } - err = _parse_gltf_state(state, p_path, p_bake_fps); + err = _parse_gltf_state(p_state, p_path); ERR_FAIL_COND_V(err != OK, err); return OK; @@ -6626,47 +6687,43 @@ Dictionary _serialize_texture_transform_uv(Vector2 p_offset, Vector2 p_scale) { } Dictionary GLTFDocument::_serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material) { - if (p_material.is_valid()) { - Vector3 offset = p_material->get_uv1_offset(); - Vector3 scale = p_material->get_uv1_scale(); - return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); - } - return Dictionary(); + ERR_FAIL_NULL_V(p_material, Dictionary()); + Vector3 offset = p_material->get_uv1_offset(); + Vector3 scale = p_material->get_uv1_scale(); + return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); } Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material) { - if (p_material.is_valid()) { - Vector3 offset = p_material->get_uv2_offset(); - Vector3 scale = p_material->get_uv2_scale(); - return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); - } - return Dictionary(); + ERR_FAIL_NULL_V(p_material, Dictionary()); + Vector3 offset = p_material->get_uv2_offset(); + Vector3 scale = p_material->get_uv2_scale(); + return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); } -Error GLTFDocument::_serialize_version(Ref<GLTFState> state) { +Error GLTFDocument::_serialize_version(Ref<GLTFState> p_state) { const String version = "2.0"; - state->major_version = version.get_slice(".", 0).to_int(); - state->minor_version = version.get_slice(".", 1).to_int(); + p_state->major_version = version.get_slice(".", 0).to_int(); + p_state->minor_version = version.get_slice(".", 1).to_int(); Dictionary asset; asset["version"] = version; String hash = String(VERSION_HASH); asset["generator"] = String(VERSION_FULL_NAME) + String("@") + (hash.is_empty() ? String("unknown") : hash); - state->json["asset"] = asset; + p_state->json["asset"] = asset; ERR_FAIL_COND_V(!asset.has("version"), Error::FAILED); - ERR_FAIL_COND_V(!state->json.has("asset"), Error::FAILED); + ERR_FAIL_COND_V(!p_state->json.has("asset"), Error::FAILED); return OK; } -Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) { +Error GLTFDocument::_serialize_file(Ref<GLTFState> p_state, const String p_path) { Error err = FAILED; if (p_path.to_lower().ends_with("glb")) { - err = _encode_buffer_glb(state, p_path); + err = _encode_buffer_glb(p_state, p_path); ERR_FAIL_COND_V(err != OK, err); - Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V(f.is_null(), FAILED); + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V(file.is_null(), FAILED); - String json = Variant(state->json).to_json_string(); + String json = Variant(p_state->json).to_json_string(); const uint32_t magic = 0x46546C67; // GLTF const int32_t header_size = 12; @@ -6677,106 +6734,104 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) { const uint32_t text_chunk_type = 0x4E4F534A; //JSON uint32_t binary_data_length = 0; - if (state->buffers.size()) { - binary_data_length = state->buffers[0].size(); + if (p_state->buffers.size()) { + binary_data_length = p_state->buffers[0].size(); } const uint32_t binary_chunk_length = ((binary_data_length + 3) & (~3)); const uint32_t binary_chunk_type = 0x004E4942; //BIN - f->create(FileAccess::ACCESS_RESOURCES); - f->store_32(magic); - f->store_32(state->major_version); // version - f->store_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_chunk_length); // length - f->store_32(text_chunk_length); - f->store_32(text_chunk_type); - f->store_buffer((uint8_t *)&cs[0], cs.length()); + file->create(FileAccess::ACCESS_RESOURCES); + file->store_32(magic); + file->store_32(p_state->major_version); // version + file->store_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_chunk_length); // length + file->store_32(text_chunk_length); + file->store_32(text_chunk_type); + file->store_buffer((uint8_t *)&cs[0], cs.length()); for (uint32_t pad_i = text_data_length; pad_i < text_chunk_length; pad_i++) { - f->store_8(' '); + file->store_8(' '); } if (binary_chunk_length) { - f->store_32(binary_chunk_length); - f->store_32(binary_chunk_type); - f->store_buffer(state->buffers[0].ptr(), binary_data_length); + file->store_32(binary_chunk_length); + file->store_32(binary_chunk_type); + file->store_buffer(p_state->buffers[0].ptr(), binary_data_length); } for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) { - f->store_8(0); + file->store_8(0); } } else { - err = _encode_buffer_bins(state, p_path); + err = _encode_buffer_bins(p_state, p_path); ERR_FAIL_COND_V(err != OK, err); - Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V(f.is_null(), FAILED); + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V(file.is_null(), FAILED); - f->create(FileAccess::ACCESS_RESOURCES); - String json = Variant(state->json).to_json_string(); - f->store_string(json); + file->create(FileAccess::ACCESS_RESOURCES); + String json = Variant(p_state->json).to_json_string(); + file->store_string(json); } return err; } void GLTFDocument::_bind_methods() { - ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps", "base_path"), - &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30), DEFVAL(String())); - ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags", "bake_fps"), - &GLTFDocument::append_from_buffer, DEFVAL(0), DEFVAL(30)); - ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags", "bake_fps"), - &GLTFDocument::append_from_scene, DEFVAL(0), DEFVAL(30)); - ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps"), - &GLTFDocument::generate_scene, DEFVAL(30)); + ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "base_path"), + &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags"), + &GLTFDocument::append_from_buffer, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags"), + &GLTFDocument::append_from_scene, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps", "trimming"), + &GLTFDocument::generate_scene, DEFVAL(30), DEFVAL(false)); ClassDB::bind_method(D_METHOD("generate_buffer", "state"), &GLTFDocument::generate_buffer); ClassDB::bind_method(D_METHOD("write_to_filesystem", "state", "path"), &GLTFDocument::write_to_filesystem); - ClassDB::bind_method(D_METHOD("set_extensions", "extensions"), - &GLTFDocument::set_extensions); - ClassDB::bind_method(D_METHOD("get_extensions"), - &GLTFDocument::get_extensions); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "extensions", PROPERTY_HINT_ARRAY_TYPE, - vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GLTFDocumentExtension"), - PROPERTY_USAGE_DEFAULT), - "set_extensions", "get_extensions"); + ClassDB::bind_static_method("GLTFDocument", D_METHOD("register_gltf_document_extension", "extension", "first_priority"), + &GLTFDocument::register_gltf_document_extension, DEFVAL(false)); + ClassDB::bind_static_method("GLTFDocument", D_METHOD("unregister_gltf_document_extension", "extension"), + &GLTFDocument::unregister_gltf_document_extension); } -void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) { +void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> p_state) { // build the hierarchy - for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { - for (int j = 0; j < state->nodes[node_i]->children.size(); j++) { - GLTFNodeIndex child_i = state->nodes[node_i]->children[j]; - ERR_FAIL_INDEX(child_i, state->nodes.size()); - if (state->nodes.write[child_i]->parent != -1) { + for (GLTFNodeIndex node_i = 0; node_i < p_state->nodes.size(); node_i++) { + for (int j = 0; j < p_state->nodes[node_i]->children.size(); j++) { + GLTFNodeIndex child_i = p_state->nodes[node_i]->children[j]; + ERR_FAIL_INDEX(child_i, p_state->nodes.size()); + if (p_state->nodes.write[child_i]->parent != -1) { continue; } - state->nodes.write[child_i]->parent = node_i; + p_state->nodes.write[child_i]->parent = node_i; } } } -void GLTFDocument::set_extensions(TypedArray<GLTFDocumentExtension> p_extensions) { - document_extensions = p_extensions; +Vector<Ref<GLTFDocumentExtension>> GLTFDocument::all_document_extensions; + +void GLTFDocument::register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority) { + if (all_document_extensions.find(p_extension) == -1) { + if (p_first_priority) { + all_document_extensions.insert(0, p_extension); + } else { + all_document_extensions.push_back(p_extension); + } + } } -TypedArray<GLTFDocumentExtension> GLTFDocument::get_extensions() const { - return document_extensions; +void GLTFDocument::unregister_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension) { + all_document_extensions.erase(p_extension); } -GLTFDocument::GLTFDocument() { - bool is_editor = ::Engine::get_singleton()->is_editor_hint(); - if (is_editor) { - return; - } - Ref<GLTFDocumentExtensionConvertImporterMesh> extension_editor; - extension_editor.instantiate(); - document_extensions.push_back(extension_editor); +void GLTFDocument::unregister_all_gltf_document_extensions() { + all_document_extensions.clear(); } -PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error *r_err) { - Error err = _encode_buffer_glb(state, ""); +PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> p_state, Error *r_err) { + Error err = _encode_buffer_glb(p_state, ""); if (r_err) { *r_err = err; } ERR_FAIL_COND_V(err != OK, PackedByteArray()); - String json = Variant(state->json).to_json_string(); + String json = Variant(p_state->json).to_json_string(); const uint32_t magic = 0x46546C67; // GLTF const int32_t header_size = 12; @@ -6790,8 +6845,8 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error const uint32_t text_chunk_type = 0x4E4F534A; //JSON int32_t binary_data_length = 0; - if (state->buffers.size()) { - binary_data_length = state->buffers[0].size(); + if (p_state->buffers.size()) { + binary_data_length = p_state->buffers[0].size(); } const int32_t binary_chunk_length = binary_data_length; const int32_t binary_chunk_type = 0x004E4942; //BIN @@ -6799,7 +6854,7 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error Ref<StreamPeerBuffer> buffer; buffer.instantiate(); buffer->put_32(magic); - buffer->put_32(state->major_version); // version + buffer->put_32(p_state->major_version); // version buffer->put_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_data_length); // length buffer->put_32(text_chunk_length); buffer->put_32(text_chunk_type); @@ -6807,211 +6862,210 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error if (binary_chunk_length) { buffer->put_32(binary_chunk_length); buffer->put_32(binary_chunk_type); - buffer->put_data(state->buffers[0].ptr(), binary_data_length); + buffer->put_data(p_state->buffers[0].ptr(), binary_data_length); } return buffer->get_data_array(); } -PackedByteArray GLTFDocument::generate_buffer(Ref<GLTFState> state) { - ERR_FAIL_NULL_V(state, PackedByteArray()); - Error err = _serialize(state, ""); +PackedByteArray GLTFDocument::generate_buffer(Ref<GLTFState> p_state) { + ERR_FAIL_NULL_V(p_state, PackedByteArray()); + Error err = _serialize(p_state, ""); ERR_FAIL_COND_V(err != OK, PackedByteArray()); - PackedByteArray bytes = _serialize_glb_buffer(state, &err); + PackedByteArray bytes = _serialize_glb_buffer(p_state, &err); return bytes; } -Error GLTFDocument::write_to_filesystem(Ref<GLTFState> state, const String &p_path) { - ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER); - Error err = _serialize(state, p_path); +Error GLTFDocument::write_to_filesystem(Ref<GLTFState> p_state, const String &p_path) { + ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); + Error err = _serialize(p_state, p_path); if (err != OK) { return err; } - err = _serialize_file(state, p_path); + err = _serialize_file(p_state, p_path); if (err != OK) { return Error::FAILED; } return OK; } -Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) { - ERR_FAIL_NULL_V(state, nullptr); - ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr); +Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool p_trimming) { + ERR_FAIL_NULL_V(p_state, nullptr); + ERR_FAIL_INDEX_V(0, p_state->root_nodes.size(), nullptr); Error err = OK; - GLTFNodeIndex gltf_root = state->root_nodes.write[0]; - Node *gltf_root_node = state->get_scene_node(gltf_root); + GLTFNodeIndex gltf_root = p_state->root_nodes.write[0]; + Node *gltf_root_node = p_state->get_scene_node(gltf_root); Node *root = gltf_root_node->get_parent(); ERR_FAIL_NULL_V(root, nullptr); - _process_mesh_instances(state, root); - if (state->get_create_animations() && state->animations.size()) { + _process_mesh_instances(p_state, root); + if (p_state->get_create_animations() && p_state->animations.size()) { AnimationPlayer *ap = memnew(AnimationPlayer); root->add_child(ap, true); ap->set_owner(root); - for (int i = 0; i < state->animations.size(); i++) { - _import_animation(state, ap, i, p_bake_fps); + for (int i = 0; i < p_state->animations.size(); i++) { + _import_animation(p_state, ap, i, p_bake_fps, p_trimming); } } - for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) { + for (KeyValue<GLTFNodeIndex, Node *> E : p_state->scene_nodes) { ERR_CONTINUE(!E.value); - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); - ERR_CONTINUE(!state->json.has("nodes")); - Array nodes = state->json["nodes"]; + ERR_CONTINUE(!p_state->json.has("nodes")); + Array nodes = p_state->json["nodes"]; ERR_CONTINUE(E.key >= nodes.size()); ERR_CONTINUE(E.key < 0); Dictionary node_json = nodes[E.key]; - Ref<GLTFNode> gltf_node = state->nodes[E.key]; - err = ext->import_node(state, gltf_node, node_json, E.value); + Ref<GLTFNode> gltf_node = p_state->nodes[E.key]; + err = ext->import_node(p_state, gltf_node, node_json, E.value); ERR_CONTINUE(err != OK); } } - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); - err = ext->import_post(state, root); + err = ext->import_post(p_state, root); ERR_CONTINUE(err != OK); } ERR_FAIL_NULL_V(root, nullptr); return root; } -Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) { - ERR_FAIL_COND_V(state.is_null(), FAILED); - state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; - state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; +Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> p_state, uint32_t p_flags) { + ERR_FAIL_COND_V(p_state.is_null(), FAILED); + p_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + p_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + document_extensions.clear(); + for (Ref<GLTFDocumentExtension> ext : all_document_extensions) { ERR_CONTINUE(ext.is_null()); - Error err = ext->export_preflight(p_node); - ERR_FAIL_COND_V(err != OK, FAILED); + Error err = ext->export_preflight(p_state, p_node); + if (err == OK) { + document_extensions.push_back(ext); + } } - _convert_scene_node(state, p_node, -1, -1); - if (!state->buffers.size()) { - state->buffers.push_back(Vector<uint8_t>()); + _convert_scene_node(p_state, p_node, -1, -1); + if (!p_state->buffers.size()) { + p_state->buffers.push_back(Vector<uint8_t>()); } return OK; } -Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) { - ERR_FAIL_COND_V(state.is_null(), FAILED); +Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> p_state, uint32_t p_flags) { + ERR_FAIL_COND_V(p_state.is_null(), FAILED); // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire Error err = FAILED; - state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; - state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; + p_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + p_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; Ref<FileAccessMemory> file_access; file_access.instantiate(); file_access->open_custom(p_bytes.ptr(), p_bytes.size()); - state->base_path = p_base_path.get_base_dir(); - err = _parse(state, state->base_path, file_access, p_bake_fps); + p_state->base_path = p_base_path.get_base_dir(); + err = _parse(p_state, p_state->base_path, file_access); ERR_FAIL_COND_V(err != OK, err); - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); - err = ext->import_post_parse(state); + err = ext->import_post_parse(p_state); ERR_FAIL_COND_V(err != OK, err); } return OK; } -Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_search_path, float p_bake_fps) { +Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> p_state, const String &p_search_path) { Error err; /* PARSE EXTENSIONS */ - err = _parse_gltf_extensions(state); + err = _parse_gltf_extensions(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE SCENE */ - err = _parse_scenes(state); + err = _parse_scenes(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE NODES */ - err = _parse_nodes(state); + err = _parse_nodes(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE BUFFERS */ - err = _parse_buffers(state, p_search_path); + err = _parse_buffers(p_state, p_search_path); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE BUFFER VIEWS */ - err = _parse_buffer_views(state); + err = _parse_buffer_views(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE ACCESSORS */ - err = _parse_accessors(state); + err = _parse_accessors(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - if (!state->discard_meshes_and_materials) { + if (!p_state->discard_meshes_and_materials) { /* PARSE IMAGES */ - err = _parse_images(state, p_search_path); + err = _parse_images(p_state, p_search_path); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE TEXTURE SAMPLERS */ - err = _parse_texture_samplers(state); + err = _parse_texture_samplers(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE TEXTURES */ - err = _parse_textures(state); + err = _parse_textures(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE TEXTURES */ - err = _parse_materials(state); + err = _parse_materials(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); } /* PARSE SKINS */ - err = _parse_skins(state); + err = _parse_skins(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* DETERMINE SKELETONS */ - err = _determine_skeletons(state); + err = _determine_skeletons(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* CREATE SKELETONS */ - err = _create_skeletons(state); + err = _create_skeletons(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* CREATE SKINS */ - err = _create_skins(state); + err = _create_skins(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE MESHES (we have enough info now) */ - err = _parse_meshes(state); + err = _parse_meshes(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE LIGHTS */ - err = _parse_lights(state); + err = _parse_lights(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE CAMERAS */ - err = _parse_cameras(state); + err = _parse_cameras(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* PARSE ANIMATIONS */ - err = _parse_animations(state); + err = _parse_animations(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* ASSIGN SCENE NAMES */ - _assign_scene_names(state); + _assign_scene_names(p_state); Node3D *root = memnew(Node3D); - for (int32_t root_i = 0; root_i < state->root_nodes.size(); root_i++) { - _generate_scene_node(state, root, root, state->root_nodes[root_i]); + for (int32_t root_i = 0; root_i < p_state->root_nodes.size(); root_i++) { + _generate_scene_node(p_state, root, root, p_state->root_nodes[root_i]); } return OK; } -Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps, String p_base_path) { +Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, String p_base_path) { // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire if (r_state == Ref<GLTFState>()) { r_state.instantiate(); @@ -7020,18 +7074,17 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint r_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; r_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; Error err; - Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err); ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN); - ERR_FAIL_NULL_V(f, ERR_FILE_CANT_OPEN); + ERR_FAIL_NULL_V(file, ERR_FILE_CANT_OPEN); String base_path = p_base_path; if (base_path.is_empty()) { base_path = p_path.get_base_dir(); } r_state->base_path = base_path; - err = _parse(r_state, base_path, f, p_bake_fps); + err = _parse(r_state, base_path, file); ERR_FAIL_COND_V(err != OK, err); - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); err = ext->import_post_parse(r_state); ERR_FAIL_COND_V(err != OK, err); @@ -7039,22 +7092,21 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint return OK; } -Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) { - ERR_FAIL_NULL_V(state, ERR_PARSE_ERROR); - if (state->json.has("extensionsUsed")) { - Vector<String> ext_array = state->json["extensionsUsed"]; - state->extensions_used = ext_array; +Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> p_state) { + ERR_FAIL_NULL_V(p_state, ERR_PARSE_ERROR); + if (p_state->json.has("extensionsUsed")) { + Vector<String> ext_array = p_state->json["extensionsUsed"]; + p_state->extensions_used = ext_array; } - if (state->json.has("extensionsRequired")) { - Vector<String> ext_array = state->json["extensionsRequired"]; - state->extensions_required = ext_array; + if (p_state->json.has("extensionsRequired")) { + Vector<String> ext_array = p_state->json["extensionsRequired"]; + p_state->extensions_required = ext_array; } HashSet<String> supported_extensions; supported_extensions.insert("KHR_lights_punctual"); supported_extensions.insert("KHR_materials_pbrSpecularGlossiness"); supported_extensions.insert("KHR_texture_transform"); - for (int ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); Vector<String> ext_supported_extensions = ext->get_supported_extensions(); for (int i = 0; i < ext_supported_extensions.size(); ++i) { @@ -7062,9 +7114,9 @@ Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) { } } Error ret = Error::OK; - for (int i = 0; i < state->extensions_required.size(); i++) { - if (!supported_extensions.has(state->extensions_required[i])) { - ERR_PRINT("GLTF: Can't import file '" + state->filename + "', required extension '" + String(state->extensions_required[i]) + "' is not supported. Are you missing a GLTFDocumentExtension plugin?"); + for (int i = 0; i < p_state->extensions_required.size(); i++) { + if (!supported_extensions.has(p_state->extensions_required[i])) { + ERR_PRINT("GLTF: Can't import file '" + p_state->filename + "', required extension '" + String(p_state->extensions_required[i]) + "' is not supported. Are you missing a GLTFDocumentExtension plugin?"); ret = ERR_UNAVAILABLE; } } diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 62b6e29fe0..6e2d0e2fd4 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -31,26 +31,19 @@ #ifndef GLTF_DOCUMENT_H #define GLTF_DOCUMENT_H -#include "gltf_defines.h" -#include "structures/gltf_animation.h" - -#include "scene/3d/bone_attachment_3d.h" -#include "scene/3d/importer_mesh_instance_3d.h" -#include "scene/3d/mesh_instance_3d.h" -#include "scene/animation/animation_player.h" -#include "scene/resources/material.h" +#include "extensions/gltf_document_extension.h" #include "modules/modules_enabled.gen.h" // For csg, gridmap. class GLTFDocument : public Resource { GDCLASS(GLTFDocument, Resource); - TypedArray<GLTFDocumentExtension> document_extensions; + static Vector<Ref<GLTFDocumentExtension>> all_document_extensions; + Vector<Ref<GLTFDocumentExtension>> document_extensions; private: const float BAKE_FPS = 30.0f; public: - GLTFDocument(); const int32_t JOINT_GROUP_SIZE = 4; enum { @@ -76,203 +69,204 @@ protected: static void _bind_methods(); public: - void set_extensions(TypedArray<GLTFDocumentExtension> p_extensions); - TypedArray<GLTFDocumentExtension> get_extensions() const; + static void register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority = false); + static void unregister_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension); + static void unregister_all_gltf_document_extensions(); private: - void _build_parent_hierachy(Ref<GLTFState> state); + void _build_parent_hierachy(Ref<GLTFState> p_state); double _filter_number(double p_float); String _get_component_type_name(const uint32_t p_component); - int _get_component_type_size(const int component_type); - Error _parse_scenes(Ref<GLTFState> state); - Error _parse_nodes(Ref<GLTFState> state); + int _get_component_type_size(const int p_component_type); + Error _parse_scenes(Ref<GLTFState> p_state); + Error _parse_nodes(Ref<GLTFState> p_state); String _get_type_name(const GLTFType p_component); String _get_accessor_type_name(const GLTFType p_type); - String _gen_unique_name(Ref<GLTFState> state, const String &p_name); - String _sanitize_animation_name(const String &name); - String _gen_unique_animation_name(Ref<GLTFState> state, const String &p_name); - String _sanitize_bone_name(const String &name); - String _gen_unique_bone_name(Ref<GLTFState> state, - const GLTFSkeletonIndex skel_i, + String _gen_unique_name(Ref<GLTFState> p_state, const String &p_name); + String _sanitize_animation_name(const String &p_name); + String _gen_unique_animation_name(Ref<GLTFState> p_state, const String &p_name); + String _sanitize_bone_name(const String &p_name); + String _gen_unique_bone_name(Ref<GLTFState> p_state, + const GLTFSkeletonIndex p_skel_i, const String &p_name); - GLTFTextureIndex _set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture, + GLTFTextureIndex _set_texture(Ref<GLTFState> p_state, Ref<Texture2D> p_texture, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats); - Ref<Texture2D> _get_texture(Ref<GLTFState> state, + Ref<Texture2D> _get_texture(Ref<GLTFState> p_state, const GLTFTextureIndex p_texture); - GLTFTextureSamplerIndex _set_sampler_for_mode(Ref<GLTFState> state, + GLTFTextureSamplerIndex _set_sampler_for_mode(Ref<GLTFState> p_state, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats); - Ref<GLTFTextureSampler> _get_sampler_for_texture(Ref<GLTFState> state, + Ref<GLTFTextureSampler> _get_sampler_for_texture(Ref<GLTFState> p_state, const GLTFTextureIndex p_texture); - Error _parse_json(const String &p_path, Ref<GLTFState> state); - Error _parse_glb(Ref<FileAccess> f, Ref<GLTFState> state); - void _compute_node_heights(Ref<GLTFState> state); - Error _parse_buffers(Ref<GLTFState> state, const String &p_base_path); - Error _parse_buffer_views(Ref<GLTFState> state); + Error _parse_json(const String &p_path, Ref<GLTFState> p_state); + Error _parse_glb(Ref<FileAccess> p_file, Ref<GLTFState> p_state); + void _compute_node_heights(Ref<GLTFState> p_state); + Error _parse_buffers(Ref<GLTFState> p_state, const String &p_base_path); + Error _parse_buffer_views(Ref<GLTFState> p_state); GLTFType _get_type_from_str(const String &p_string); - Error _parse_accessors(Ref<GLTFState> state); - Error _decode_buffer_view(Ref<GLTFState> state, double *dst, + Error _parse_accessors(Ref<GLTFState> p_state); + Error _decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, const GLTFBufferViewIndex p_buffer_view, - const int skip_every, const int skip_bytes, - const int element_size, const int count, - const GLTFType type, const int component_count, - const int component_type, const int component_size, - const bool normalized, const int byte_offset, - const bool for_vertex); - Vector<double> _decode_accessor(Ref<GLTFState> state, + const int p_skip_every, const int p_skip_bytes, + const int p_element_size, const int p_count, + const GLTFType p_type, const int p_component_count, + const int p_component_type, const int p_component_size, + const bool p_normalized, const int p_byte_offset, + const bool p_for_vertex); + Vector<double> _decode_accessor(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<float> _decode_accessor_as_floats(Ref<GLTFState> state, + Vector<float> _decode_accessor_as_floats(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<int> _decode_accessor_as_ints(Ref<GLTFState> state, + Vector<int> _decode_accessor_as_ints(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<Vector2> _decode_accessor_as_vec2(Ref<GLTFState> state, + Vector<Vector2> _decode_accessor_as_vec2(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<Vector3> _decode_accessor_as_vec3(Ref<GLTFState> state, + Vector<Vector3> _decode_accessor_as_vec3(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<Color> _decode_accessor_as_color(Ref<GLTFState> state, + Vector<Color> _decode_accessor_as_color(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<Quaternion> _decode_accessor_as_quaternion(Ref<GLTFState> state, + Vector<Quaternion> _decode_accessor_as_quaternion(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<Transform2D> _decode_accessor_as_xform2d(Ref<GLTFState> state, + Vector<Transform2D> _decode_accessor_as_xform2d(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<Basis> _decode_accessor_as_basis(Ref<GLTFState> state, + Vector<Basis> _decode_accessor_as_basis(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Vector<Transform3D> _decode_accessor_as_xform(Ref<GLTFState> state, + Vector<Transform3D> _decode_accessor_as_xform(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); - Error _parse_meshes(Ref<GLTFState> state); - Error _serialize_textures(Ref<GLTFState> state); - Error _serialize_texture_samplers(Ref<GLTFState> state); - Error _serialize_images(Ref<GLTFState> state, const String &p_path); - Error _serialize_lights(Ref<GLTFState> state); - Error _parse_images(Ref<GLTFState> state, const String &p_base_path); - Error _parse_textures(Ref<GLTFState> state); - Error _parse_texture_samplers(Ref<GLTFState> state); - Error _parse_materials(Ref<GLTFState> state); - void _set_texture_transform_uv1(const Dictionary &d, Ref<BaseMaterial3D> material); + Error _parse_meshes(Ref<GLTFState> p_state); + Error _serialize_textures(Ref<GLTFState> p_state); + Error _serialize_texture_samplers(Ref<GLTFState> p_state); + Error _serialize_images(Ref<GLTFState> p_state, const String &p_path); + Error _serialize_lights(Ref<GLTFState> p_state); + Error _parse_images(Ref<GLTFState> p_state, const String &p_base_path); + Error _parse_textures(Ref<GLTFState> p_state); + Error _parse_texture_samplers(Ref<GLTFState> p_state); + Error _parse_materials(Ref<GLTFState> p_state); + void _set_texture_transform_uv1(const Dictionary &d, Ref<BaseMaterial3D> p_material); void spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Ref<BaseMaterial3D> p_material); static void spec_gloss_to_metal_base_color(const Color &p_specular_factor, const Color &p_diffuse, Color &r_base_color, float &r_metallic); - GLTFNodeIndex _find_highest_node(Ref<GLTFState> state, - const Vector<GLTFNodeIndex> &subset); - bool _capture_nodes_in_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin, - const GLTFNodeIndex node_index); - void _capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin); - Error _expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin); - Error _verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin); - Error _parse_skins(Ref<GLTFState> state); - Error _determine_skeletons(Ref<GLTFState> state); + GLTFNodeIndex _find_highest_node(Ref<GLTFState> p_state, + const Vector<GLTFNodeIndex> &p_subset); + bool _capture_nodes_in_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin, + const GLTFNodeIndex p_node_index); + void _capture_nodes_for_multirooted_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin); + Error _expand_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin); + Error _verify_skin(Ref<GLTFState> p_state, Ref<GLTFSkin> p_skin); + Error _parse_skins(Ref<GLTFState> p_state); + Error _determine_skeletons(Ref<GLTFState> p_state); Error _reparent_non_joint_skeleton_subtrees( - Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton, - const Vector<GLTFNodeIndex> &non_joints); - Error _determine_skeleton_roots(Ref<GLTFState> state, - const GLTFSkeletonIndex skel_i); - Error _create_skeletons(Ref<GLTFState> state); - Error _map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFState> state); - Error _serialize_skins(Ref<GLTFState> state); - Error _create_skins(Ref<GLTFState> state); - bool _skins_are_same(const Ref<Skin> skin_a, const Ref<Skin> skin_b); - void _remove_duplicate_skins(Ref<GLTFState> state); - Error _serialize_cameras(Ref<GLTFState> state); - Error _parse_cameras(Ref<GLTFState> state); - Error _parse_lights(Ref<GLTFState> state); - Error _parse_animations(Ref<GLTFState> state); - Error _serialize_animations(Ref<GLTFState> state); - BoneAttachment3D *_generate_bone_attachment(Ref<GLTFState> state, - Skeleton3D *skeleton, - const GLTFNodeIndex node_index, - const GLTFNodeIndex bone_index); - ImporterMeshInstance3D *_generate_mesh_instance(Ref<GLTFState> state, const GLTFNodeIndex node_index); - Camera3D *_generate_camera(Ref<GLTFState> state, const GLTFNodeIndex node_index); - Light3D *_generate_light(Ref<GLTFState> state, const GLTFNodeIndex node_index); - Node3D *_generate_spatial(Ref<GLTFState> state, const GLTFNodeIndex node_index); - void _assign_scene_names(Ref<GLTFState> state); + Ref<GLTFState> p_state, Ref<GLTFSkeleton> p_skeleton, + const Vector<GLTFNodeIndex> &p_non_joints); + Error _determine_skeleton_roots(Ref<GLTFState> p_state, + const GLTFSkeletonIndex p_skel_i); + Error _create_skeletons(Ref<GLTFState> p_state); + Error _map_skin_joints_indices_to_skeleton_bone_indices(Ref<GLTFState> p_state); + Error _serialize_skins(Ref<GLTFState> p_state); + Error _create_skins(Ref<GLTFState> p_state); + bool _skins_are_same(const Ref<Skin> p_skin_a, const Ref<Skin> p_skin_b); + void _remove_duplicate_skins(Ref<GLTFState> p_state); + Error _serialize_cameras(Ref<GLTFState> p_state); + Error _parse_cameras(Ref<GLTFState> p_state); + Error _parse_lights(Ref<GLTFState> p_state); + Error _parse_animations(Ref<GLTFState> p_state); + Error _serialize_animations(Ref<GLTFState> p_state); + BoneAttachment3D *_generate_bone_attachment(Ref<GLTFState> p_state, + Skeleton3D *p_skeleton, + const GLTFNodeIndex p_node_index, + const GLTFNodeIndex p_bone_index); + ImporterMeshInstance3D *_generate_mesh_instance(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index); + Camera3D *_generate_camera(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index); + Light3D *_generate_light(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index); + Node3D *_generate_spatial(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index); + void _assign_scene_names(Ref<GLTFState> p_state); template <class T> T _interpolate_track(const Vector<real_t> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp); - GLTFAccessorIndex _encode_accessor_as_quaternions(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_quaternions(Ref<GLTFState> p_state, const Vector<Quaternion> p_attribs, const bool p_for_vertex); - GLTFAccessorIndex _encode_accessor_as_weights(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_weights(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex); - GLTFAccessorIndex _encode_accessor_as_joints(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_joints(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex); - GLTFAccessorIndex _encode_accessor_as_floats(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_floats(Ref<GLTFState> p_state, const Vector<real_t> p_attribs, const bool p_for_vertex); - GLTFAccessorIndex _encode_accessor_as_vec2(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_vec2(Ref<GLTFState> p_state, const Vector<Vector2> p_attribs, const bool p_for_vertex); - void _calc_accessor_vec2_min_max(int i, const int element_count, Vector<double> &type_max, Vector2 attribs, Vector<double> &type_min) { - if (i == 0) { - for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.write[type_i] = attribs[(i * element_count) + type_i]; - type_min.write[type_i] = attribs[(i * element_count) + type_i]; + void _calc_accessor_vec2_min_max(int p_i, const int p_element_count, Vector<double> &p_type_max, Vector2 p_attribs, Vector<double> &p_type_min) { + if (p_i == 0) { + for (int32_t type_i = 0; type_i < p_element_count; type_i++) { + p_type_max.write[type_i] = p_attribs[(p_i * p_element_count) + type_i]; + p_type_min.write[type_i] = p_attribs[(p_i * p_element_count) + type_i]; } } - for (int32_t type_i = 0; type_i < element_count; type_i++) { - type_max.write[type_i] = MAX(attribs[(i * element_count) + type_i], type_max[type_i]); - type_min.write[type_i] = MIN(attribs[(i * element_count) + type_i], type_min[type_i]); - type_max.write[type_i] = _filter_number(type_max.write[type_i]); - type_min.write[type_i] = _filter_number(type_min.write[type_i]); + for (int32_t type_i = 0; type_i < p_element_count; type_i++) { + p_type_max.write[type_i] = MAX(p_attribs[(p_i * p_element_count) + type_i], p_type_max[type_i]); + p_type_min.write[type_i] = MIN(p_attribs[(p_i * p_element_count) + type_i], p_type_min[type_i]); + p_type_max.write[type_i] = _filter_number(p_type_max.write[type_i]); + p_type_min.write[type_i] = _filter_number(p_type_min.write[type_i]); } } - GLTFAccessorIndex _encode_accessor_as_vec3(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_vec3(Ref<GLTFState> p_state, const Vector<Vector3> p_attribs, const bool p_for_vertex); - GLTFAccessorIndex _encode_accessor_as_color(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_color(Ref<GLTFState> p_state, const Vector<Color> p_attribs, const bool p_for_vertex); void _calc_accessor_min_max(int p_i, const int p_element_count, Vector<double> &p_type_max, Vector<double> p_attribs, Vector<double> &p_type_min); - GLTFAccessorIndex _encode_accessor_as_ints(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_ints(Ref<GLTFState> p_state, const Vector<int32_t> p_attribs, const bool p_for_vertex); - GLTFAccessorIndex _encode_accessor_as_xform(Ref<GLTFState> state, + GLTFAccessorIndex _encode_accessor_as_xform(Ref<GLTFState> p_state, const Vector<Transform3D> p_attribs, const bool p_for_vertex); - Error _encode_buffer_view(Ref<GLTFState> state, const double *src, - const int count, const GLTFType type, - const int component_type, const bool normalized, - const int byte_offset, const bool for_vertex, + Error _encode_buffer_view(Ref<GLTFState> p_state, const double *p_src, + const int p_count, const GLTFType p_type, + const int p_component_type, const bool p_normalized, + const int p_byte_offset, const bool p_for_vertex, GLTFBufferViewIndex &r_accessor); - Error _encode_accessors(Ref<GLTFState> state); - Error _encode_buffer_views(Ref<GLTFState> state); - Error _serialize_materials(Ref<GLTFState> state); - Error _serialize_meshes(Ref<GLTFState> state); - Error _serialize_nodes(Ref<GLTFState> state); - Error _serialize_scenes(Ref<GLTFState> state); + Error _encode_accessors(Ref<GLTFState> p_state); + Error _encode_buffer_views(Ref<GLTFState> p_state); + Error _serialize_materials(Ref<GLTFState> p_state); + Error _serialize_meshes(Ref<GLTFState> p_state); + Error _serialize_nodes(Ref<GLTFState> p_state); + Error _serialize_scenes(Ref<GLTFState> p_state); String interpolation_to_string(const GLTFAnimation::Interpolation p_interp); - GLTFAnimation::Track _convert_animation_track(Ref<GLTFState> state, + GLTFAnimation::Track _convert_animation_track(Ref<GLTFState> p_state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, int32_t p_track_i, GLTFNodeIndex p_node_i); - Error _encode_buffer_bins(Ref<GLTFState> state, const String &p_path); - Error _encode_buffer_glb(Ref<GLTFState> state, const String &p_path); - PackedByteArray _serialize_glb_buffer(Ref<GLTFState> state, Error *r_err); + Error _encode_buffer_bins(Ref<GLTFState> p_state, const String &p_path); + Error _encode_buffer_glb(Ref<GLTFState> p_state, const String &p_path); + PackedByteArray _serialize_glb_buffer(Ref<GLTFState> p_state, Error *r_err); Dictionary _serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material); Dictionary _serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material); - Error _serialize_version(Ref<GLTFState> state); - Error _serialize_file(Ref<GLTFState> state, const String p_path); - Error _serialize_gltf_extensions(Ref<GLTFState> state) const; + Error _serialize_version(Ref<GLTFState> p_state); + Error _serialize_file(Ref<GLTFState> p_state, const String p_path); + Error _serialize_gltf_extensions(Ref<GLTFState> p_state) const; public: // https://www.itu.int/rec/R-REC-BT.601 @@ -284,90 +278,90 @@ public: private: // https://github.com/microsoft/glTF-SDK/blob/master/GLTFSDK/Source/PBRUtils.cpp#L9 // https://bghgary.github.io/glTF/convert-between-workflows-bjs/js/babylon.pbrUtilities.js - static float solve_metallic(float p_dielectric_specular, float diffuse, - float specular, + static float solve_metallic(float p_dielectric_specular, float p_diffuse, + float p_specular, float p_one_minus_specular_strength); static float get_perceived_brightness(const Color p_color); static float get_max_component(const Color &p_color); public: - Error append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30, String p_base_path = String()); - Error append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30); - Error append_from_scene(Node *p_node, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30); + Error append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, String p_base_path = String()); + Error append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> r_state, uint32_t p_flags = 0); + Error append_from_scene(Node *p_node, Ref<GLTFState> r_state, uint32_t p_flags = 0); public: - Node *generate_scene(Ref<GLTFState> state, int32_t p_bake_fps = 30.0f); - PackedByteArray generate_buffer(Ref<GLTFState> state); - Error write_to_filesystem(Ref<GLTFState> state, const String &p_path); + Node *generate_scene(Ref<GLTFState> p_state, float p_bake_fps = 30.0f, bool p_trimming = false); + PackedByteArray generate_buffer(Ref<GLTFState> p_state); + Error write_to_filesystem(Ref<GLTFState> p_state, const String &p_path); public: - Error _parse_gltf_state(Ref<GLTFState> state, const String &p_search_path, float p_bake_fps); - Error _parse_gltf_extensions(Ref<GLTFState> state); - void _process_mesh_instances(Ref<GLTFState> state, Node *scene_root); - void _generate_scene_node(Ref<GLTFState> state, Node *scene_parent, - Node3D *scene_root, - const GLTFNodeIndex node_index); - void _generate_skeleton_bone_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index); - void _import_animation(Ref<GLTFState> state, AnimationPlayer *ap, - const GLTFAnimationIndex index, const int bake_fps); - void _convert_mesh_instances(Ref<GLTFState> state); - GLTFCameraIndex _convert_camera(Ref<GLTFState> state, Camera3D *p_camera); - void _convert_light_to_gltf(Light3D *light, Ref<GLTFState> state, Ref<GLTFNode> gltf_node); - GLTFLightIndex _convert_light(Ref<GLTFState> state, Light3D *p_light); - void _convert_spatial(Ref<GLTFState> state, Node3D *p_spatial, Ref<GLTFNode> p_node); - void _convert_scene_node(Ref<GLTFState> state, Node *p_current, + Error _parse_gltf_state(Ref<GLTFState> p_state, const String &p_search_path); + Error _parse_gltf_extensions(Ref<GLTFState> p_state); + void _process_mesh_instances(Ref<GLTFState> p_state, Node *p_scene_root); + void _generate_scene_node(Ref<GLTFState> p_state, Node *p_scene_parent, + Node3D *p_scene_root, + const GLTFNodeIndex p_node_index); + void _generate_skeleton_bone_node(Ref<GLTFState> p_state, Node *p_scene_parent, Node3D *p_scene_root, const GLTFNodeIndex p_node_index); + void _import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, + const GLTFAnimationIndex p_index, const float p_bake_fps, const bool p_trimming); + void _convert_mesh_instances(Ref<GLTFState> p_state); + GLTFCameraIndex _convert_camera(Ref<GLTFState> p_state, Camera3D *p_camera); + void _convert_light_to_gltf(Light3D *p_light, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node); + GLTFLightIndex _convert_light(Ref<GLTFState> p_state, Light3D *p_light); + void _convert_spatial(Ref<GLTFState> p_state, Node3D *p_spatial, Ref<GLTFNode> p_node); + void _convert_scene_node(Ref<GLTFState> p_state, Node *p_current, const GLTFNodeIndex p_gltf_current, const GLTFNodeIndex p_gltf_root); #ifdef MODULE_CSG_ENABLED - void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> gltf_node, Ref<GLTFState> state); + void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state); #endif // MODULE_CSG_ENABLED - void _create_gltf_node(Ref<GLTFState> state, + void _create_gltf_node(Ref<GLTFState> p_state, Node *p_scene_parent, - GLTFNodeIndex current_node_i, + GLTFNodeIndex p_current_node_i, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, - Ref<GLTFNode> gltf_node); + Ref<GLTFNode> p_gltf_node); void _convert_animation_player_to_gltf( - AnimationPlayer *animation_player, Ref<GLTFState> state, + AnimationPlayer *p_animation_player, Ref<GLTFState> p_state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent); - void _check_visibility(Node *p_node, bool &retflag); - void _convert_camera_to_gltf(Camera3D *camera, Ref<GLTFState> state, - Ref<GLTFNode> gltf_node); + void _check_visibility(Node *p_node, bool &r_retflag); + void _convert_camera_to_gltf(Camera3D *p_camera, Ref<GLTFState> p_state, + Ref<GLTFNode> p_gltf_node); #ifdef MODULE_GRIDMAP_ENABLED void _convert_grid_map_to_gltf( GridMap *p_grid_map, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, - Ref<GLTFNode> gltf_node, Ref<GLTFState> state); + Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state); #endif // MODULE_GRIDMAP_ENABLED void _convert_multi_mesh_instance_to_gltf( MultiMeshInstance3D *p_multi_mesh_instance, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, - Ref<GLTFNode> gltf_node, Ref<GLTFState> state); + Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state); void _convert_skeleton_to_gltf( - Skeleton3D *p_scene_parent, Ref<GLTFState> state, + Skeleton3D *p_scene_parent, Ref<GLTFState> p_state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, - Ref<GLTFNode> gltf_node); + Ref<GLTFNode> p_gltf_node); void _convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_attachment, - Ref<GLTFState> state, + Ref<GLTFState> p_state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, - Ref<GLTFNode> gltf_node); + Ref<GLTFNode> p_gltf_node); void _convert_mesh_instance_to_gltf(MeshInstance3D *p_mesh_instance, - Ref<GLTFState> state, - Ref<GLTFNode> gltf_node); - GLTFMeshIndex _convert_mesh_to_gltf(Ref<GLTFState> state, + Ref<GLTFState> p_state, + Ref<GLTFNode> p_gltf_node); + GLTFMeshIndex _convert_mesh_to_gltf(Ref<GLTFState> p_state, MeshInstance3D *p_mesh_instance); - void _convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, + void _convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, String p_animation_track_name); - Error _serialize(Ref<GLTFState> state, const String &p_path); - Error _parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> f, int p_bake_fps); + Error _serialize(Ref<GLTFState> p_state, const String &p_path); + Error _parse(Ref<GLTFState> p_state, String p_path, Ref<FileAccess> p_file); }; #endif // GLTF_DOCUMENT_H diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index ac5665e396..9f6cb20935 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -30,6 +30,8 @@ #include "gltf_state.h" +#include "gltf_template_convert.h" + void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("add_used_extension", "extension_name", "required"), &GLTFState::add_used_extension); ClassDB::bind_method(D_METHOD("get_json"), &GLTFState::get_json); @@ -209,11 +211,11 @@ void GLTFState::set_meshes(TypedArray<GLTFMesh> p_meshes) { GLTFTemplateConvert::set_from_array(meshes, p_meshes); } -TypedArray<BaseMaterial3D> GLTFState::get_materials() { +TypedArray<Material> GLTFState::get_materials() { return GLTFTemplateConvert::to_array(materials); } -void GLTFState::set_materials(TypedArray<BaseMaterial3D> p_materials) { +void GLTFState::set_materials(TypedArray<Material> p_materials) { GLTFTemplateConvert::set_from_array(materials, p_materials); } diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index e24017b0fd..e264da69e0 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -32,7 +32,6 @@ #define GLTF_STATE_H #include "extensions/gltf_light.h" -#include "gltf_template_convert.h" #include "structures/gltf_accessor.h" #include "structures/gltf_animation.h" #include "structures/gltf_buffer_view.h" @@ -44,10 +43,6 @@ #include "structures/gltf_texture.h" #include "structures/gltf_texture_sampler.h" -#include "core/templates/rb_map.h" -#include "scene/animation/animation_player.h" -#include "scene/resources/texture.h" - class GLTFState : public Resource { GDCLASS(GLTFState, Resource); friend class GLTFDocument; @@ -72,8 +67,8 @@ class GLTFState : public Resource { Vector<Ref<GLTFMesh>> meshes; // meshes are loaded directly, no reason not to. Vector<AnimationPlayer *> animation_players; - HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex> material_cache; - Vector<Ref<BaseMaterial3D>> materials; + HashMap<Ref<Material>, GLTFMaterialIndex> material_cache; + Vector<Ref<Material>> materials; String scene_name; Vector<int> root_nodes; @@ -138,8 +133,8 @@ public: TypedArray<GLTFMesh> get_meshes(); void set_meshes(TypedArray<GLTFMesh> p_meshes); - TypedArray<BaseMaterial3D> get_materials(); - void set_materials(TypedArray<BaseMaterial3D> p_materials); + TypedArray<Material> get_materials(); + void set_materials(TypedArray<Material> p_materials); String get_scene_name(); void set_scene_name(String p_scene_name); @@ -194,21 +189,6 @@ public: Variant get_additional_data(const StringName &p_extension_name); void set_additional_data(const StringName &p_extension_name, Variant p_additional_data); - - //void set_scene_nodes(RBMap<GLTFNodeIndex, Node *> p_scene_nodes) { - // this->scene_nodes = p_scene_nodes; - //} - - //void set_animation_players(Vector<AnimationPlayer *> p_animation_players) { - // this->animation_players = p_animation_players; - //} - - //RBMap<Ref<Material>, GLTFMaterialIndex> get_material_cache() { - // return this->material_cache; - //} - //void set_material_cache(RBMap<Ref<Material>, GLTFMaterialIndex> p_material_cache) { - // this->material_cache = p_material_cache; - //} }; #endif // GLTF_STATE_H diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index b9027f6e3d..2322e13ae2 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -30,24 +30,9 @@ #include "register_types.h" -#ifndef _3D_DISABLED - -#include "extensions/gltf_light.h" +#include "extensions/gltf_document_extension_convert_importer_mesh.h" #include "extensions/gltf_spec_gloss.h" #include "gltf_document.h" -#include "gltf_document_extension.h" -#include "gltf_document_extension_convert_importer_mesh.h" -#include "gltf_state.h" -#include "structures/gltf_accessor.h" -#include "structures/gltf_animation.h" -#include "structures/gltf_buffer_view.h" -#include "structures/gltf_camera.h" -#include "structures/gltf_mesh.h" -#include "structures/gltf_node.h" -#include "structures/gltf_skeleton.h" -#include "structures/gltf_skin.h" -#include "structures/gltf_texture.h" -#include "structures/gltf_texture_sampler.h" #ifdef TOOLS_ENABLED #include "core/config/project_settings.h" @@ -95,20 +80,22 @@ static void _editor_init() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "filesystem/import/fbx/fbx2gltf_path", PROPERTY_HINT_GLOBAL_FILE)); if (fbx_enabled) { - Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - if (fbx2gltf_path.is_empty()) { - WARN_PRINT("FBX file import is enabled in the project settings, but no FBX2glTF path is configured in the editor settings. FBX files will not be imported."); - } else if (!da->file_exists(fbx2gltf_path)) { - WARN_PRINT("FBX file import is enabled, but the FBX2glTF path doesn't point to an accessible file. FBX files will not be imported."); - } else { - Ref<EditorSceneFormatImporterFBX> importer; - importer.instantiate(); - ResourceImporterScene::add_importer(importer); - } + Ref<EditorSceneFormatImporterFBX> importer; + importer.instantiate(); + ResourceImporterScene::get_scene_singleton()->add_importer(importer); + + Ref<EditorFileSystemImportFormatSupportQueryFBX> fbx_import_query; + fbx_import_query.instantiate(); + EditorFileSystem::get_singleton()->add_import_format_support_query(fbx_import_query); } } #endif // TOOLS_ENABLED +#define GLTF_REGISTER_DOCUMENT_EXTENSION(m_doc_ext_class) \ + Ref<m_doc_ext_class> extension_##m_doc_ext_class; \ + extension_##m_doc_ext_class.instantiate(); \ + GLTFDocument::register_gltf_document_extension(extension_##m_doc_ext_class); + void initialize_gltf_module(ModuleInitializationLevel p_level) { if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) { // glTF API available at runtime. @@ -128,6 +115,11 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(GLTFState); GDREGISTER_CLASS(GLTFTexture); GDREGISTER_CLASS(GLTFTextureSampler); + // Register GLTFDocumentExtension classes with GLTFDocument. + bool is_editor = ::Engine::get_singleton()->is_editor_hint(); + if (!is_editor) { + GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionConvertImporterMesh); + } } #ifdef TOOLS_ENABLED @@ -161,6 +153,5 @@ void uninitialize_gltf_module(ModuleInitializationLevel p_level) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { return; } + GLTFDocument::unregister_all_gltf_document_extensions(); } - -#endif // _3D_DISABLED diff --git a/modules/gltf/structures/gltf_accessor.h b/modules/gltf/structures/gltf_accessor.h index bfb71d57fe..8e4bb2d3f9 100644 --- a/modules/gltf/structures/gltf_accessor.h +++ b/modules/gltf/structures/gltf_accessor.h @@ -31,9 +31,8 @@ #ifndef GLTF_ACCESSOR_H #define GLTF_ACCESSOR_H -#include "core/io/resource.h" - #include "../gltf_defines.h" +#include "core/io/resource.h" struct GLTFAccessor : public Resource { GDCLASS(GLTFAccessor, Resource); diff --git a/modules/gltf/structures/gltf_animation.h b/modules/gltf/structures/gltf_animation.h index 3777f579f6..fc535631bb 100644 --- a/modules/gltf/structures/gltf_animation.h +++ b/modules/gltf/structures/gltf_animation.h @@ -31,7 +31,7 @@ #ifndef GLTF_ANIMATION_H #define GLTF_ANIMATION_H -#include "core/io/resource.h" +#include "scene/animation/animation_player.h" class GLTFAnimation : public Resource { GDCLASS(GLTFAnimation, Resource); diff --git a/modules/gltf/structures/gltf_buffer_view.cpp b/modules/gltf/structures/gltf_buffer_view.cpp index ba19ed8628..a15141225b 100644 --- a/modules/gltf/structures/gltf_buffer_view.cpp +++ b/modules/gltf/structures/gltf_buffer_view.cpp @@ -30,8 +30,6 @@ #include "gltf_buffer_view.h" -#include "../gltf_document_extension.h" - void GLTFBufferView::_bind_methods() { ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer); ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &GLTFBufferView::set_buffer); diff --git a/modules/gltf/structures/gltf_camera.cpp b/modules/gltf/structures/gltf_camera.cpp index 212b9b80c8..7a5ab2763c 100644 --- a/modules/gltf/structures/gltf_camera.cpp +++ b/modules/gltf/structures/gltf_camera.cpp @@ -30,6 +30,8 @@ #include "gltf_camera.h" +#include "scene/3d/camera_3d.h" + void GLTFCamera::_bind_methods() { ClassDB::bind_static_method("GLTFCamera", D_METHOD("from_node", "camera_node"), &GLTFCamera::from_node); ClassDB::bind_method(D_METHOD("to_node"), &GLTFCamera::to_node); diff --git a/modules/gltf/structures/gltf_camera.h b/modules/gltf/structures/gltf_camera.h index 50ae10e17a..5e8a1da5f7 100644 --- a/modules/gltf/structures/gltf_camera.h +++ b/modules/gltf/structures/gltf_camera.h @@ -32,7 +32,8 @@ #define GLTF_CAMERA_H #include "core/io/resource.h" -#include "scene/3d/camera_3d.h" + +class Camera3D; // Reference and test file: // https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_015_SimpleCameras.md @@ -64,7 +65,7 @@ public: real_t get_depth_near() const { return depth_near; } void set_depth_near(real_t p_val) { depth_near = p_val; } - static Ref<GLTFCamera> from_node(const Camera3D *p_light); + static Ref<GLTFCamera> from_node(const Camera3D *p_camera); Camera3D *to_node() const; static Ref<GLTFCamera> from_dictionary(const Dictionary p_dictionary); diff --git a/modules/gltf/structures/gltf_mesh.h b/modules/gltf/structures/gltf_mesh.h index 2fa37fd727..92722ce75c 100644 --- a/modules/gltf/structures/gltf_mesh.h +++ b/modules/gltf/structures/gltf_mesh.h @@ -31,10 +31,8 @@ #ifndef GLTF_MESH_H #define GLTF_MESH_H -#include "core/io/resource.h" -#include "scene/3d/importer_mesh_instance_3d.h" +#include "../gltf_defines.h" #include "scene/resources/importer_mesh.h" -#include "scene/resources/mesh.h" class GLTFMesh : public Resource { GDCLASS(GLTFMesh, Resource); diff --git a/modules/gltf/structures/gltf_texture_sampler.h b/modules/gltf/structures/gltf_texture_sampler.h index 3fad31bbee..7bb7cd62e3 100644 --- a/modules/gltf/structures/gltf_texture_sampler.h +++ b/modules/gltf/structures/gltf_texture_sampler.h @@ -31,7 +31,6 @@ #ifndef GLTF_TEXTURE_SAMPLER_H #define GLTF_TEXTURE_SAMPLER_H -#include "core/io/resource.h" #include "scene/resources/material.h" class GLTFTextureSampler : public Resource { |