Merge pull request #91560 from ydeltastar/retarget-axis-fix
Make retarget keep global rest of unmapped bones if there are no mapped bones on the child
This commit is contained in:
commit
55b8724bd5
|
@ -41,8 +41,9 @@ void PostImportPluginSkeletonRestFixer::get_internal_import_options(InternalImpo
|
|||
if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/apply_node_transforms"), true));
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/normalize_position_tracks"), true));
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/overwrite_axis"), true));
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/reset_all_bone_poses_after_import"), true));
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/overwrite_axis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/keep_global_rest_on_leftovers"), true));
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/fix_silhouette/enable", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
|
||||
// TODO: PostImportPlugin need to be implemented such as validate_option(PropertyInfo &property, const Dictionary &p_options).
|
||||
// get_internal_option_visibility() is not sufficient because it can only retrieve options implemented in the core and can only read option values.
|
||||
|
@ -61,6 +62,8 @@ Variant PostImportPluginSkeletonRestFixer::get_internal_option_visibility(Intern
|
|||
return false;
|
||||
}
|
||||
}
|
||||
} else if (p_option == "retarget/rest_fixer/keep_global_rest_on_leftovers") {
|
||||
return bool(p_options["retarget/rest_fixer/overwrite_axis"]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -460,6 +463,48 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||
old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
|
||||
}
|
||||
|
||||
bool keep_global_rest_leftovers = bool(p_options["retarget/rest_fixer/keep_global_rest_on_leftovers"]);
|
||||
|
||||
// Scan hierarchy and populate a whitelist of unmapped bones without mapped descendants.
|
||||
Vector<int> keep_bone_rest;
|
||||
if (keep_global_rest_leftovers) {
|
||||
Vector<int> bones_to_process = src_skeleton->get_parentless_bones();
|
||||
while (bones_to_process.size() > 0) {
|
||||
int src_idx = bones_to_process[0];
|
||||
bones_to_process.erase(src_idx);
|
||||
Vector<int> src_children = src_skeleton->get_bone_children(src_idx);
|
||||
for (const int &src_child : src_children) {
|
||||
bones_to_process.push_back(src_child);
|
||||
}
|
||||
|
||||
StringName src_bone_name = is_renamed ? StringName(src_skeleton->get_bone_name(src_idx)) : bone_map->find_profile_bone_name(src_skeleton->get_bone_name(src_idx));
|
||||
if (src_bone_name != StringName() && !profile->has_bone(src_bone_name)) {
|
||||
// Scan descendants for mapped bones.
|
||||
bool found_mapped = false;
|
||||
|
||||
Vector<int> decendants_to_process = src_skeleton->get_bone_children(src_idx);
|
||||
while (decendants_to_process.size() > 0) {
|
||||
int desc_idx = decendants_to_process[0];
|
||||
decendants_to_process.erase(desc_idx);
|
||||
Vector<int> desc_children = src_skeleton->get_bone_children(desc_idx);
|
||||
for (const int &desc_child : desc_children) {
|
||||
decendants_to_process.push_back(desc_child);
|
||||
}
|
||||
|
||||
StringName desc_bone_name = is_renamed ? StringName(src_skeleton->get_bone_name(desc_idx)) : bone_map->find_profile_bone_name(src_skeleton->get_bone_name(desc_idx));
|
||||
if (desc_bone_name != StringName() && profile->has_bone(desc_bone_name)) {
|
||||
found_mapped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_mapped) {
|
||||
keep_bone_rest.push_back(src_idx); // No mapped descendants. Add to whitelist.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector<Basis> diffs;
|
||||
diffs.resize(src_skeleton->get_bone_count());
|
||||
Basis *diffs_w = diffs.ptrw();
|
||||
|
@ -485,13 +530,9 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||
int prof_idx = profile->find_bone(src_bone_name);
|
||||
if (prof_idx >= 0) {
|
||||
tgt_rot = src_pg.inverse() * prof_skeleton->get_bone_global_rest(prof_idx).basis; // Mapped bone uses reference pose.
|
||||
} else if (keep_global_rest_leftovers && keep_bone_rest.has(src_idx)) {
|
||||
tgt_rot = src_pg.inverse() * old_skeleton_global_rest[src_idx].basis; // Non-Mapped bone without mapped children keeps global rest.
|
||||
}
|
||||
/*
|
||||
// If there is rest-relative animation, this logic may be work fine, but currently not so...
|
||||
} else {
|
||||
// tgt_rot = src_pg.inverse() * old_skeleton_global_rest[src_idx].basis; // Non-Mapped bone keeps global rest.
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (src_skeleton->get_bone_parent(src_idx) >= 0) {
|
||||
|
|
Loading…
Reference in New Issue