diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 999b4d2b641..1a2cab248ac 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 109 +#define BLENDER_FILE_SUBVERSION 110 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index 196ad3ca5e8..9ba230ebc46 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -3501,6 +3501,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) * later during 5.0 development process. */ version_system_idprops_nodes_generate(main); } + if (!MAIN_VERSION_FILE_ATLEAST(main, 500, 110)) { + /* Same as above, but children bones were missed by initial versioning code, attempt to + * transfer idprops data still in case they have no system properties defined yet. */ + version_system_idprops_children_bones_generate(main); + } if (G.debug & G_DEBUG) { char build_commit_datetime[32]; diff --git a/source/blender/blenloader/intern/versioning_500.cc b/source/blender/blenloader/intern/versioning_500.cc index 4aca1992862..c7273c791d0 100644 --- a/source/blender/blenloader/intern/versioning_500.cc +++ b/source/blender/blenloader/intern/versioning_500.cc @@ -130,8 +130,16 @@ void version_system_idprops_generate(Main *bmain) for (BoneCollection *bcoll : armature->collections_span()) { idprops_process(bcoll->prop, &bcoll->system_properties); } - LISTBASE_FOREACH (Bone *, bone, &armature->bonebase) { + /* There is no way to iterate directly over all bones of an armature currently, use a recursive + * approach instead. */ + auto process_bone_recursive = [](const auto &process_bone_recursive, Bone *bone) -> void { idprops_process(bone->prop, &bone->system_properties); + LISTBASE_FOREACH (Bone *, bone_it, &bone->childbase) { + process_bone_recursive(process_bone_recursive, bone_it); + } + }; + LISTBASE_FOREACH (Bone *, bone_it, &armature->bonebase) { + process_bone_recursive(process_bone_recursive, bone_it); } } } @@ -145,6 +153,29 @@ void version_system_idprops_nodes_generate(Main *bmain) } FOREACH_NODETREE_END; } +/* Separate callback for non-root bones, because they were missed in the initial implementation. */ +void version_system_idprops_children_bones_generate(Main *bmain) +{ + LISTBASE_FOREACH (bArmature *, armature, &bmain->armatures) { + /* There is no way to iterate directly over all bones of an armature currently, use a recursive + * approach instead. */ + auto process_bone_recursive = [](const auto &process_bone_recursive, Bone *bone) -> void { + /* Do not overwrite children bones' system properties if they were already defined by some + * scripts or add-on e.g. */ + if (bone->system_properties == nullptr) { + idprops_process(bone->prop, &bone->system_properties); + } + LISTBASE_FOREACH (Bone *, bone_it, &bone->childbase) { + process_bone_recursive(process_bone_recursive, bone_it); + } + }; + LISTBASE_FOREACH (Bone *, bone_it, &armature->bonebase) { + LISTBASE_FOREACH (Bone *, bone_child_it, &bone_it->childbase) { + process_bone_recursive(process_bone_recursive, bone_child_it); + } + } + } +} static CustomDataLayer *find_old_seam_layer(CustomData &custom_data, const blender::StringRef name) { diff --git a/source/blender/blenloader/intern/versioning_common.hh b/source/blender/blenloader/intern/versioning_common.hh index 0f83f2e48f3..0dd284787e3 100644 --- a/source/blender/blenloader/intern/versioning_common.hh +++ b/source/blender/blenloader/intern/versioning_common.hh @@ -218,6 +218,7 @@ bNode *version_eevee_output_node_get(bNodeTree *ntree, int16_t node_type); */ void version_system_idprops_generate(Main *bmain); void version_system_idprops_nodes_generate(Main *bmain); +void version_system_idprops_children_bones_generate(Main *bmain); bool all_scenes_use(Main *bmain, const blender::Span engines);