From a56b3a93d36a2c564c749ff49ca5a450fd73888a Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Tue, 10 Jun 2025 00:41:33 -0700 Subject: [PATCH] Implement naming version system for FBX and Blend importers like glTF --- .../fbx/editor/editor_scene_importer_fbx2gltf.cpp | 11 +++++++++++ modules/fbx/editor/editor_scene_importer_ufbx.cpp | 11 +++++++++++ modules/fbx/fbx_document.cpp | 14 +++++++++++++- modules/fbx/fbx_document.h | 3 +++ .../gltf/editor/editor_scene_importer_blend.cpp | 15 +++++++++++++++ modules/gltf/editor/editor_scene_importer_blend.h | 1 + modules/gltf/skin_tool.h | 2 +- 7 files changed, 55 insertions(+), 2 deletions(-) diff --git a/modules/fbx/editor/editor_scene_importer_fbx2gltf.cpp b/modules/fbx/editor/editor_scene_importer_fbx2gltf.cpp index 6174717330f..949be212f7d 100644 --- a/modules/fbx/editor/editor_scene_importer_fbx2gltf.cpp +++ b/modules/fbx/editor/editor_scene_importer_fbx2gltf.cpp @@ -98,6 +98,10 @@ Node *EditorSceneFormatImporterFBX2GLTF::import_scene(const String &p_path, uint gltf.instantiate(); Ref state; state.instantiate(); + if (p_options.has("fbx/naming_version")) { + int naming_version = p_options["fbx/naming_version"]; + gltf->set_naming_version(naming_version); + } if (p_options.has(SNAME("nodes/import_as_skeleton_bones")) ? (bool)p_options[SNAME("nodes/import_as_skeleton_bones")] : false) { state->set_import_as_skeleton_bones(true); } @@ -133,10 +137,17 @@ Variant EditorSceneFormatImporterFBX2GLTF::get_option_visibility(const String &p void EditorSceneFormatImporterFBX2GLTF::get_import_options(const String &p_path, List *r_options) { + // This function must be empty to avoid both FBX2glTF and UFBX adding the same options to FBX files. } void EditorSceneFormatImporterFBX2GLTF::handle_compatibility_options(HashMap &p_import_params) const { if (!p_import_params.has("fbx/importer")) { p_import_params["fbx/importer"] = EditorSceneFormatImporterUFBX::FBX_IMPORTER_UFBX; } + if (!p_import_params.has("fbx/naming_version")) { + // If a .fbx's existing import file is missing the FBX + // naming compatibility version, we need to use version 1. + // Version 1 is the behavior before this option was added. + p_import_params["fbx/naming_version"] = 1; + } } diff --git a/modules/fbx/editor/editor_scene_importer_ufbx.cpp b/modules/fbx/editor/editor_scene_importer_ufbx.cpp index 9c359359130..48c2cbe5041 100644 --- a/modules/fbx/editor/editor_scene_importer_ufbx.cpp +++ b/modules/fbx/editor/editor_scene_importer_ufbx.cpp @@ -59,6 +59,10 @@ Node *EditorSceneFormatImporterUFBX::import_scene(const String &p_path, uint32_t state.instantiate(); print_verbose(vformat("FBX path: %s", p_path)); String path = ProjectSettings::get_singleton()->globalize_path(p_path); + if (p_options.has("fbx/naming_version")) { + int naming_version = p_options["fbx/naming_version"]; + fbx->set_naming_version(naming_version); + } bool allow_geometry_helper_nodes = p_options.has("fbx/allow_geometry_helper_nodes") ? (bool)p_options["fbx/allow_geometry_helper_nodes"] : false; if (allow_geometry_helper_nodes) { state->set_allow_geometry_helper_nodes(allow_geometry_helper_nodes); @@ -94,6 +98,7 @@ void EditorSceneFormatImporterUFBX::get_import_options(const String &p_path, r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "fbx/importer", PROPERTY_HINT_ENUM, "ufbx,FBX2glTF"), FBX_IMPORTER_UFBX)); r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::BOOL, "fbx/allow_geometry_helper_nodes"), false)); r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "fbx/embedded_image_handling", PROPERTY_HINT_ENUM, "Discard All Textures,Extract Textures,Embed as Basis Universal,Embed as Uncompressed", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), FBXState::HANDLE_BINARY_EXTRACT_TEXTURES)); + r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "fbx/naming_version", PROPERTY_HINT_ENUM, "Godot 4.0 or 4.1,Godot 4.2 to 4.4,Godot 4.5 or later"), 2)); } } @@ -101,4 +106,10 @@ void EditorSceneFormatImporterUFBX::handle_compatibility_options(HashMap p_state, const String &p_searc ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* DETERMINE SKELETONS */ - err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->get_import_as_skeleton_bones() ? p_state->root_nodes : Vector()); + if (p_state->get_import_as_skeleton_bones()) { + err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->root_nodes, true); + } else { + err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, Vector(), _naming_version < 2); + } ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); /* CREATE SKELETONS */ @@ -2490,6 +2494,14 @@ Error FBXDocument::append_from_scene(Node *p_node, Ref p_state, uint3 return ERR_UNAVAILABLE; } +void FBXDocument::set_naming_version(int p_version) { + _naming_version = p_version; +} + +int FBXDocument::get_naming_version() const { + return _naming_version; +} + Vector3 FBXDocument::_as_vec3(const ufbx_vec3 &p_vector) { return Vector3(real_t(p_vector.x), real_t(p_vector.y), real_t(p_vector.z)); } diff --git a/modules/fbx/fbx_document.h b/modules/fbx/fbx_document.h index 40a017107bf..3ef4f604f25 100644 --- a/modules/fbx/fbx_document.h +++ b/modules/fbx/fbx_document.h @@ -62,6 +62,9 @@ public: PackedByteArray generate_buffer(Ref p_state) override; Error write_to_filesystem(Ref p_state, const String &p_path) override; + void set_naming_version(int p_version); + int get_naming_version() const; + private: String _get_texture_path(const String &p_base_directory, const String &p_source_file_path) const; void _process_uv_set(PackedVector2Array &uv_array); diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 6fd08436108..c0fc3100877 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -299,6 +299,10 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ Ref state; state.instantiate(); + if (p_options.has("gltf/naming_version")) { + int naming_version = p_options["gltf/naming_version"]; + gltf->set_naming_version(naming_version); + } if (p_options.has(SNAME("nodes/import_as_skeleton_bones")) ? (bool)p_options[SNAME("nodes/import_as_skeleton_bones")] : false) { state->set_import_as_skeleton_bones(true); } @@ -364,6 +368,17 @@ void EditorSceneFormatImporterBlend::get_import_options(const String &p_path, Li ADD_OPTION_BOOL("blender/animation/limit_playback", true); ADD_OPTION_BOOL("blender/animation/always_sample", true); ADD_OPTION_BOOL("blender/animation/group_tracks", true); + + r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "gltf/naming_version", PROPERTY_HINT_ENUM, "Godot 4.0 or 4.1,Godot 4.2 to 4.4,Godot 4.5 or later"), 2)); +} + +void EditorSceneFormatImporterBlend::handle_compatibility_options(HashMap &p_import_params) const { + if (!p_import_params.has("gltf/naming_version")) { + // If a .blend's existing import file is missing the glTF + // naming compatibility version, we need to use version 1. + // Version 1 is the behavior before this option was added. + p_import_params["gltf/naming_version"] = 1; + } } /////////////////////////// diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index 996f897f418..1f78a298766 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -72,6 +72,7 @@ public: List *r_options) override; virtual Variant get_option_visibility(const String &p_path, const String &p_scene_import_type, const String &p_option, const HashMap &p_options) override; + virtual void handle_compatibility_options(HashMap &p_import_params) const override; }; class LineEdit; diff --git a/modules/gltf/skin_tool.h b/modules/gltf/skin_tool.h index b3f3f8dab8e..c3604f2fb42 100644 --- a/modules/gltf/skin_tool.h +++ b/modules/gltf/skin_tool.h @@ -90,7 +90,7 @@ public: Vector> &r_nodes, Vector> &r_skeletons, const Vector &p_single_skeleton_root, - bool p_turn_non_joint_descendants_into_bones = false); + bool p_turn_non_joint_descendants_into_bones); static Error _create_skeletons( HashSet &r_unique_names, Vector> &r_skins,