Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-10-20 07:44:35 +0400
committerJoshua Leung <aligorith@gmail.com>2009-10-20 07:44:35 +0400
commit7f133f65b2049546adddec77720c90aafb9add97 (patch)
treec7ebbb8eb317f0dea27f9f338debe9e1f49035d6 /source/blender
parent9e6d1c6cfaf5e06d734a2a1124bd4ee3c030fd38 (diff)
Bugfix #19663: Renaming named data doesn't fix F-Curves
RNA Paths used in F-Curve, Drivers, etc. now get renamed when some data that they use gets renamed. This only works when things like Bones, Constraints, Shape Keys, and Modifiers get renamed, but other cases can get added easily. The code here only performs simple string replacements, so there is the potential for problems when several sets of data with the same names are present. For example, if there are multiple armatures with bones that have the same names, renaming a bone on one armature (with a bone on another armature having the same name) will break all the drivers on the other one, even though they aren't really connected. However, I don't expect the aforementioned scenario to really be a problem in most production scenarios.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_animsys.h10
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c156
-rw-r--r--source/blender/editors/armature/editarmature.c11
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/intern/rna_access.c75
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c7
-rw-r--r--source/blender/makesrna/intern/rna_key.c24
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c7
8 files changed, 269 insertions, 23 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index cc5b4dfdcaf..045095567bc 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -67,6 +67,7 @@ struct KeyingSet *BKE_keyingset_add(struct ListBase *list, const char name[], sh
/* Add a destination to a KeyingSet */
void BKE_keyingset_add_destination(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode);
+/* Find the destination matching the criteria given */
struct KS_Path *BKE_keyingset_find_destination(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode);
/* Copy all KeyingSets in the given list */
@@ -79,6 +80,15 @@ void BKE_keyingset_free(struct KeyingSet *ks);
void BKE_keyingsets_free(struct ListBase *list);
/* ************************************* */
+/* Path Fixing API */
+
+/* Fix all the paths for the given ID+AnimData */
+void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, char *prefix, char *oldName, char *newName);
+
+/* Fix all the paths for the entire database... */
+void BKE_all_animdata_fix_paths_rename(char *prefix, char *oldName, char *newName);
+
+/* ************************************* */
// TODO: overrides, remapping, and path-finding api's
/* ************************************* */
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 47f5dd116d7..316ac484484 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -238,24 +238,69 @@ void BKE_animdata_make_local(AnimData *adt)
/* Path Validation -------------------------------------------- */
-#if 0
-/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate */
-static char *rna_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, char *oldpath)
+/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate
+ *
+ * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
+ * i.e. pose.pose_channels["Bone"]
+ */
+static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldpath)
{
+ char *prefixPtr= strstr(oldpath, prefix);
+ char *oldNamePtr= strstr(oldpath, oldName);
+ int prefixLen= strlen(prefix);
+ int oldNameLen= strlen(oldName);
+ /* only start fixing the path if the prefix and oldName feature in the path,
+ * and prefix occurs immediately before oldName (the +2 should take care of any [")
+ */
+ if ( (prefixPtr && oldNamePtr) && (prefixPtr+prefixLen+2 == oldNamePtr) ) {
+ DynStr *ds= BLI_dynstr_new();
+ char *postfixPtr= oldNamePtr+oldNameLen+2;
+ char *newPath = NULL;
+ char oldChar;
+
+ /* add the part of the string that goes up to the start of the prefix */
+ if (prefixPtr > oldpath) {
+ oldChar= prefixPtr[0];
+ prefixPtr[0]= 0;
+ BLI_dynstr_append(ds, oldpath);
+ prefixPtr[0]= oldChar;
+ }
+
+ /* add the prefix, and opening brackets */
+ BLI_dynstr_append(ds, prefix);
+ BLI_dynstr_append(ds, "[\"");
+
+ /* add the new name */
+ BLI_dynstr_append(ds, newName);
+
+ /* add the closing brackets, then the postfix */
+ BLI_dynstr_append(ds, "\"]");
+ BLI_dynstr_append(ds, postfixPtr);
+
+ /* create new path, and cleanup old data */
+ newPath= BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ MEM_freeN(oldpath);
+
+ /* return the new path */
+ return newPath;
+ }
- return oldpath; // FIXME!!!
+ /* the old path doesn't need to be changed */
+ return oldpath;
}
/* Check RNA-Paths for a list of F-Curves */
-static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *curves)
+static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *curves)
{
FCurve *fcu;
/* we need to check every curve... */
for (fcu= curves->first; fcu; fcu= fcu->next) {
/* firstly, handle the F-Curve's own path */
- fcu->rna_path= rna_path_rename_fix(owner_id, modPtr, newName, fcu->rna_path);
+ fcu->rna_path= rna_path_rename_fix(owner_id, prefix, oldName, newName, fcu->rna_path);
/* driver? */
if (fcu->driver) {
@@ -264,14 +309,14 @@ static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *new
/* driver targets */
for (dtar= driver->targets.first; dtar; dtar=dtar->next) {
- dtat->rna_path= rna_path_rename_fix(dtar->id, modPtr, newName, dtar->rna_path);
+ dtar->rna_path= rna_path_rename_fix(dtar->id, prefix, oldName, newName, dtar->rna_path);
}
}
}
}
/* Fix all RNA-Paths for Actions linked to NLA Strips */
-static void nlastrips_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *strips)
+static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *strips)
{
NlaStrip *strip;
@@ -279,42 +324,113 @@ static void nlastrips_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *n
for (strip= strips->first; strip; strip= strip->next) {
/* fix strip's action */
if (strip->act)
- fcurves_path_rename_fix(owner_id, modPtr, newName, &strip->act->curves);
+ fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &strip->act->curves);
/* ignore own F-Curves, since those are local... */
/* check sub-strips (if metas) */
- nlastrips_path_rename_fix(owner_id, modPtr, newName, &strip->strips);
+ nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, &strip->strips);
}
}
/* Fix all RNA-Paths in the AnimData block used by the given ID block
- * - the pointer of interest must not have had its new name assigned already, otherwise
- * path matching for this will never work
+ * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
+ * i.e. pose.pose_channels["Bone"]
*/
-void BKE_animdata_fix_paths_rename (ID *owner_id, PointerRNA *modPtr, char *newName)
+void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, char *oldName, char *newName)
{
- AnimData *adt= BKE_animdata_from_id(owner_id);
NlaTrack *nlt;
/* if no AnimData, no need to proceed */
- if (ELEM4(NULL, owner_id, adt, modPtr, newName))
+ if (ELEM4(NULL, owner_id, adt, oldName, newName))
return;
/* Active action and temp action */
if (adt->action)
- fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->action->curves);
+ fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &adt->action->curves);
if (adt->tmpact)
- fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->tmpact->curves);
+ fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &adt->tmpact->curves);
/* Drivers - Drivers are really F-Curves */
- fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->drivers);
+ fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &adt->drivers);
/* NLA Data - Animation Data for Strips */
- for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
+ nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, &nlt->strips);
+}
+
+/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
+ * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
+ * i.e. pose.pose_channels["Bone"]
+ */
+void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newName)
+{
+ Main *mainptr= G.main;
+ ID *id;
+
+ /* macro for less typing
+ * - whether animdata exists is checked for by the main renaming callback, though taking
+ * this outside of the function may make things slightly faster?
+ */
+#define RENAMEFIX_ANIM_IDS(first) \
+ for (id= first; id; id= id->next) { \
+ AnimData *adt= BKE_animdata_from_id(id); \
+ BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName);\
+ }
+
+ /* nodes */
+ RENAMEFIX_ANIM_IDS(mainptr->nodetree.first);
+
+ /* textures */
+ RENAMEFIX_ANIM_IDS(mainptr->tex.first);
+
+ /* lamps */
+ RENAMEFIX_ANIM_IDS(mainptr->lamp.first);
+
+ /* materials */
+ RENAMEFIX_ANIM_IDS(mainptr->mat.first);
+
+ /* cameras */
+ RENAMEFIX_ANIM_IDS(mainptr->camera.first);
+
+ /* shapekeys */
+ RENAMEFIX_ANIM_IDS(mainptr->key.first);
+
+ /* metaballs */
+ RENAMEFIX_ANIM_IDS(mainptr->mball.first);
+
+ /* curves */
+ RENAMEFIX_ANIM_IDS(mainptr->curve.first);
+
+ /* armatures */
+ RENAMEFIX_ANIM_IDS(mainptr->armature.first);
+
+ /* meshes */
+ // TODO...
+
+ /* particles */
+ RENAMEFIX_ANIM_IDS(mainptr->particle.first);
+
+ /* objects */
+ RENAMEFIX_ANIM_IDS(mainptr->object.first);
+
+ /* worlds */
+ RENAMEFIX_ANIM_IDS(mainptr->world.first);
+
+ /* scenes */
+ for (id= mainptr->scene.first; id; id= id->next) {
+ AnimData *adt= BKE_animdata_from_id(id);
+ Scene *scene= (Scene *)id;
+
+ /* do compositing nodes first (since these aren't included in main tree) */
+ if (scene->nodetree) {
+ AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
+ BKE_animdata_fix_paths_rename((ID *)scene->nodetree, adt2, prefix, oldName, newName);
+ }
+ /* now fix scene animation data as per normal */
+ BKE_animdata_fix_paths_rename((ID *)id, adt, prefix, oldName, newName);
}
}
-#endif
/* *********************************** */
/* KeyingSet API */
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index 0343fea5bfb..1c2ec920d41 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -5289,9 +5289,8 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
/* now check if we're in editmode, we need to find the unique name */
if (arm->edbo) {
- EditBone *eBone;
+ EditBone *eBone= editbone_name_exists(arm->edbo, oldname);
- eBone= editbone_name_exists(arm->edbo, oldname);
if (eBone) {
unique_editbone_name(arm->edbo, newname, NULL);
BLI_strncpy(eBone->name, newname, MAXBONENAME);
@@ -5302,7 +5301,7 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
Bone *bone= get_named_bone(arm, oldname);
if (bone) {
- unique_bone_name (arm, newname);
+ unique_bone_name(arm, newname);
BLI_strncpy(bone->name, newname, MAXBONENAME);
}
else return;
@@ -5379,6 +5378,12 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
BLI_strncpy(dg->name, newname, MAXBONENAME);
}
}
+
+ /* Fix animation data attached to this object */
+ if (ob->adt) {
+ /* posechannels only... */
+ BKE_animdata_fix_paths_rename(&ob->id, ob->adt, "pose.pose_channels", oldname, newname);
+ }
}
/* do entire db - ipo's for the drivers */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 810fb110f7a..a3cdf29669f 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -704,6 +704,8 @@ char *RNA_path_back(const char *path);
int RNA_path_resolve(PointerRNA *ptr, const char *path,
PointerRNA *r_ptr, PropertyRNA **r_prop);
+int RNA_path_resolve_next(PointerRNA *ptr, char **path,
+ PointerRNA *r_ptr, PropertyRNA **r_prop);
char *RNA_path_from_ID_to_struct(PointerRNA *ptr);
char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 6cf2fd0c60f..a2202b36c0c 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -2216,6 +2216,81 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int
return buf;
}
+/* Resolve the given RNA path to find the next pointer+property pointed to in the path */
+// NOTE: this is the same as the code below, except that we don't have the while() loop to traverse the entire path
+int RNA_path_resolve_next(PointerRNA *ptr, char **path, PointerRNA *r_ptr, PropertyRNA **r_prop)
+{
+ PropertyRNA *prop;
+ PointerRNA curptr, nextptr;
+ char fixedbuf[256], *token;
+ int len, intkey;
+
+ prop= NULL;
+ curptr= *ptr;
+
+ if ((path == NULL) || (*path == 0))
+ return 0;
+
+ /* look up property name in current struct */
+ token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 0);
+ if (!token)
+ return 0;
+
+ prop= RNA_struct_find_property(&curptr, token);
+
+ if(token != fixedbuf)
+ MEM_freeN(token);
+ if (!prop)
+ return 0;
+
+ /* now look up the value of this property if it is a pointer or
+ * collection, otherwise return the property rna so that the
+ * caller can read the value of the property itself */
+ if(RNA_property_type(prop) == PROP_POINTER) {
+ nextptr= RNA_property_pointer_get(&curptr, prop);
+
+ if(nextptr.data)
+ curptr= nextptr;
+ else
+ return 0;
+ }
+ else if(RNA_property_type(prop) == PROP_COLLECTION && *path) {
+ /* resolve the lookup with [] brackets */
+ token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
+
+ if(!token)
+ return 0;
+
+ len= strlen(token);
+
+ /* check for "" to see if it is a string */
+ if(len >= 2 && token[0] == '"' && token[len-1] == '"') {
+ /* strip away "" */
+ token[len-1]= 0;
+ RNA_property_collection_lookup_string(&curptr, prop, token+1, &nextptr);
+ }
+ else {
+ /* otherwise do int lookup */
+ intkey= atoi(token);
+ RNA_property_collection_lookup_int(&curptr, prop, intkey, &nextptr);
+ }
+
+ if(token != fixedbuf)
+ MEM_freeN(token);
+
+ if(nextptr.data)
+ curptr= nextptr;
+ else
+ return 0;
+ }
+
+ *r_ptr= curptr;
+ *r_prop= prop;
+
+ return 1;
+}
+
+/* Resolve the given RNA path to find the pointer+property indicated at the end of the path */
int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
{
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 53c8db6ff0f..54097f25b99 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -155,6 +155,10 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr)
static void rna_Constraint_name_set(PointerRNA *ptr, const char *value)
{
bConstraint *con= ptr->data;
+ char oldname[32];
+
+ /* make a copy of the old name first */
+ BLI_strncpy(oldname, con->name, sizeof(oldname));
/* copy the new name into the name slot */
BLI_strncpy(con->name, value, sizeof(con->name));
@@ -168,6 +172,9 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value)
if (list)
unique_constraint_name(con, list);
}
+
+ /* fix all the animation data which may link to this */
+ BKE_all_animdata_fix_paths_rename("constraints", oldname, con->name);
}
static char *rna_Constraint_path(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 230ed90c131..1e1eb9b055f 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -37,6 +37,8 @@
#ifdef RNA_RUNTIME
+#include <stddef.h>
+
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -47,6 +49,27 @@
#include "WM_api.h"
#include "WM_types.h"
+void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value)
+{
+ KeyBlock *kb= ptr->data;
+ char oldname[32];
+
+ /* make a copy of the old name first */
+ BLI_strncpy(oldname, kb->name, sizeof(oldname));
+
+ /* copy the new name into the name slot */
+ BLI_strncpy(kb->name, value, sizeof(kb->name));
+
+ /* make sure the name is truly unique */
+ if (ptr->id.data) {
+ Key *key= ptr->id.data;
+ BLI_uniquename(&key->block, kb, "Key", '.', offsetof(KeyBlock, name), 32);
+ }
+
+ /* fix all the animation data which may link to this */
+ BKE_all_animdata_fix_paths_rename("keys", oldname, kb->name);
+}
+
static void rna_ShapeKey_value_set(PointerRNA *ptr, float value)
{
KeyBlock *data= (KeyBlock*)ptr->data;
@@ -353,6 +376,7 @@ static void rna_def_keyblock(BlenderRNA *brna)
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ShapeKey_name_set");
RNA_def_struct_name_property(srna, prop);
/* keys need to be sorted to edit this */
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 1be610ee392..91df7800156 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -168,6 +168,10 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr)
void rna_Modifier_name_set(PointerRNA *ptr, const char *value)
{
ModifierData *md= ptr->data;
+ char oldname[32];
+
+ /* make a copy of the old name first */
+ BLI_strncpy(oldname, md->name, sizeof(oldname));
/* copy the new name into the name slot */
BLI_strncpy(md->name, value, sizeof(md->name));
@@ -177,6 +181,9 @@ void rna_Modifier_name_set(PointerRNA *ptr, const char *value)
Object *ob= ptr->id.data;
modifier_unique_name(&ob->modifiers, md);
}
+
+ /* fix all the animation data which may link to this */
+ BKE_all_animdata_fix_paths_rename("modifiers", oldname, md->name);
}
static char *rna_Modifier_path(PointerRNA *ptr)