Refactor: Anim, make pastebuf_match_path_property() easier to read
Simplify `pastebuf_match_path_property()` by reducing cognitive complexity and using `StringRef::endswith()` instead of pointer arithmetic. I've also added a few unit test cases that cover some unwanted behavior: the property name check only checks suffixes, and so copying "….location" will also paste it to a "….not_actually_location" F-Curve. No functional changes. Pull Request: https://projects.blender.org/blender/blender/pulls/133005
This commit is contained in:
@@ -1454,8 +1454,8 @@ bool pastebuf_match_path_full(Main * /*bmain*/,
|
||||
}
|
||||
|
||||
/* The 'source' of the copy data is considered 'ok' if either we're copying a single F-Curve, or
|
||||
* the array index matches (so 'loc' X/Y/Z can be copied to a single 'scale' property, and it'll
|
||||
* pick up the right X/Y/Z component). */
|
||||
* the array index matches (so [location X,Y,Z] can be copied to a single 'scale' property, and
|
||||
* it'll pick up the right X/Y/Z component). */
|
||||
const bool is_source_ok = from_single || aci->array_index == fcu->array_index;
|
||||
if (!is_source_ok) {
|
||||
return false;
|
||||
@@ -1477,46 +1477,45 @@ bool pastebuf_match_path_property(Main *bmain,
|
||||
const bool /*to_simple*/,
|
||||
const bool /*flip*/)
|
||||
{
|
||||
/* check that paths exist */
|
||||
if (aci->rna_path && fcu->rna_path) {
|
||||
/* find the property of the fcurve and compare against the end of the tAnimCopybufItem
|
||||
* more involved since it needs to do path lookups.
|
||||
* This is not 100% reliable since the user could be editing the curves on a path that won't
|
||||
* resolve, or a bone could be renamed after copying for eg. but in normal copy & paste
|
||||
* this should work out ok.
|
||||
*/
|
||||
if (BLI_findindex(which_libbase(bmain, aci->id_type), aci->id) == -1) {
|
||||
/* pedantic but the ID could have been removed, and beats crashing! */
|
||||
printf("paste_animedit_keys: error ID has been removed!\n");
|
||||
}
|
||||
else {
|
||||
PointerRNA rptr;
|
||||
PropertyRNA *prop;
|
||||
|
||||
PointerRNA id_ptr = RNA_id_pointer_create(aci->id);
|
||||
|
||||
if (RNA_path_resolve_property(&id_ptr, aci->rna_path, &rptr, &prop)) {
|
||||
const char *identifier = RNA_property_identifier(prop);
|
||||
int len_id = strlen(identifier);
|
||||
int len_path = strlen(fcu->rna_path);
|
||||
if (len_id <= len_path) {
|
||||
/* NOTE: paths which end with "] will fail with this test - Animated ID Props. */
|
||||
if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) {
|
||||
if ((from_single) || (aci->array_index == fcu->array_index)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n",
|
||||
aci->id->name,
|
||||
aci->rna_path);
|
||||
}
|
||||
}
|
||||
if (!aci->rna_path || !fcu->rna_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
/* The 'source' of the copy data is considered 'ok' if either we're copying a single F-Curve, or
|
||||
* the array index matches (so [location X,Y,Z] can be copied to a single 'scale' property, and
|
||||
* it'll pick up the right X/Y/Z component). */
|
||||
const bool is_source_ok = from_single || aci->array_index == fcu->array_index;
|
||||
if (!is_source_ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* find the property of the fcurve and compare against the end of the tAnimCopybufItem
|
||||
* more involved since it needs to do path lookups.
|
||||
* This is not 100% reliable since the user could be editing the curves on a path that won't
|
||||
* resolve, or a bone could be renamed after copying for eg. but in normal copy & paste
|
||||
* this should work out ok.
|
||||
*/
|
||||
if (BLI_findindex(which_libbase(bmain, aci->id_type), aci->id) == -1) {
|
||||
/* The ID could have been removed after copying the keys. This function
|
||||
* needs it to resolve the property & get the name. */
|
||||
printf("paste_animedit_keys: error ID has been removed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
PointerRNA rptr;
|
||||
PropertyRNA *prop;
|
||||
PointerRNA id_ptr = RNA_id_pointer_create(aci->id);
|
||||
|
||||
if (!RNA_path_resolve_property(&id_ptr, aci->rna_path, &rptr, &prop)) {
|
||||
printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n",
|
||||
aci->id->name,
|
||||
aci->rna_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *identifier = RNA_property_identifier(prop);
|
||||
/* NOTE: paths which end with "] will fail with this test - Animated ID Props. */
|
||||
return blender::StringRef(fcu->rna_path).endswith(identifier);
|
||||
}
|
||||
|
||||
bool pastebuf_match_index_only(Main * /*bmain*/,
|
||||
|
||||
@@ -496,6 +496,19 @@ TEST(keyframes_paste, pastebuf_match_path_property)
|
||||
to_simple,
|
||||
flip))
|
||||
<< "nonexistent bone, but same property name";
|
||||
|
||||
/* This just tests the current functionality. This may not necessarily be
|
||||
* correct / desired behavior. */
|
||||
FCurvePtr fcurve_with_long_rna_path = fake_fcurve(
|
||||
"pose.bones[\"hand.L\"].weirdly_long_location", 0);
|
||||
EXPECT_TRUE(pastebuf_match_path_property(
|
||||
bmain,
|
||||
fcurve.get(),
|
||||
fake_aci_owned("pose.bones[\"hand.L\"].location", 0, true, arm_ob_id).get(),
|
||||
from_single,
|
||||
to_simple,
|
||||
flip))
|
||||
<< "property name suffix-match";
|
||||
}
|
||||
|
||||
{ /* From Multiple Channels, so array indices matter. */
|
||||
@@ -558,6 +571,19 @@ TEST(keyframes_paste, pastebuf_match_path_property)
|
||||
to_simple,
|
||||
flip))
|
||||
<< "nonexistent bone, but same property name";
|
||||
|
||||
/* This just tests the current functionality. This may not necessarily be
|
||||
* correct / desired behavior. */
|
||||
FCurvePtr fcurve_with_long_rna_path = fake_fcurve(
|
||||
"pose.bones[\"hand.L\"].weirdly_long_location", 0);
|
||||
EXPECT_TRUE(pastebuf_match_path_property(
|
||||
bmain,
|
||||
fcurve.get(),
|
||||
fake_aci_owned("pose.bones[\"hand.L\"].location", 0, true, arm_ob_id).get(),
|
||||
from_single,
|
||||
to_simple,
|
||||
flip))
|
||||
<< "property name suffix-match";
|
||||
}
|
||||
|
||||
{ /* Resilience against deleted IDs. */
|
||||
|
||||
Reference in New Issue
Block a user