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>2012-05-05 19:54:08 +0400
committerJoshua Leung <aligorith@gmail.com>2012-05-05 19:54:08 +0400
commitff4ff9c8a429d9869e7056417bc7acd47a545eb2 (patch)
treea964667f39d4d0300676210f52303e68fd447e96
parent34b18fcbc18c6d89a1a1516d19c489994e4964dc (diff)
Bugfixes for various ID-block references (Constraints, NLA)
* ID-blocks referenced by Constraints but not being used as the target objects (such as Actions in the Action Constraint, or Text Blocks in PyConstraints) now get usercounts for being referenced in this way. This should fix ancient bugs such as [#19205] and [#8593]. More tests still needed to verify that this does now play nicely with proxies. * Changing actions used by NLA strips should now update the usercounts accordingly
-rw-r--r--source/blender/blenkernel/BKE_constraint.h2
-rw-r--r--source/blender/blenkernel/intern/constraint.c78
-rw-r--r--source/blender/blenloader/intern/readfile.c15
-rw-r--r--source/blender/makesrna/intern/rna_animation.c2
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c4
-rw-r--r--source/blender/makesrna/intern/rna_nla.c2
6 files changed, 62 insertions, 41 deletions
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index f834ad5e774..b12ab538184 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -62,7 +62,7 @@ typedef struct bConstraintOb {
/* ---------------------------------------------------------------------------- */
/* Callback format for performing operations on ID-pointers for Constraints */
-typedef void (*ConstraintIDFunc)(struct bConstraint *con, struct ID **idpoin, void *userdata);
+typedef void (*ConstraintIDFunc)(struct bConstraint *con, struct ID **idpoin, short isReference, void *userdata);
/* ....... */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 399aedc914f..a244fa96fda 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -781,7 +781,7 @@ static void childof_id_looper (bConstraint *con, ConstraintIDFunc func, void *us
bChildOfConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int childof_get_tars (bConstraint *con, ListBase *list)
@@ -917,7 +917,7 @@ static void trackto_id_looper (bConstraint *con, ConstraintIDFunc func, void *us
bTrackToConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int trackto_get_tars (bConstraint *con, ListBase *list)
@@ -1098,10 +1098,10 @@ static void kinematic_id_looper (bConstraint *con, ConstraintIDFunc func, void *
bKinematicConstraint *data= con->data;
/* chain target */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
/* poletarget */
- func(con, (ID**)&data->poletar, userdata);
+ func(con, (ID**)&data->poletar, FALSE, userdata);
}
static int kinematic_get_tars (bConstraint *con, ListBase *list)
@@ -1191,7 +1191,7 @@ static void followpath_id_looper (bConstraint *con, ConstraintIDFunc func, void
bFollowPathConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int followpath_get_tars (bConstraint *con, ListBase *list)
@@ -1541,7 +1541,7 @@ static void loclike_id_looper (bConstraint *con, ConstraintIDFunc func, void *us
bLocateLikeConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int loclike_get_tars (bConstraint *con, ListBase *list)
@@ -1632,7 +1632,7 @@ static void rotlike_id_looper (bConstraint *con, ConstraintIDFunc func, void *us
bChildOfConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int rotlike_get_tars (bConstraint *con, ListBase *list)
@@ -1745,7 +1745,7 @@ static void sizelike_id_looper (bConstraint *con, ConstraintIDFunc func, void *u
bSizeLikeConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int sizelike_get_tars (bConstraint *con, ListBase *list)
@@ -1835,7 +1835,7 @@ static void translike_id_looper (bConstraint *con, ConstraintIDFunc func, void *
bTransLikeConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int translike_get_tars (bConstraint *con, ListBase *list)
@@ -2007,10 +2007,10 @@ static void pycon_id_looper (bConstraint *con, ConstraintIDFunc func, void *user
/* targets */
for (ct= data->targets.first; ct; ct= ct->next)
- func(con, (ID**)&ct->tar, userdata);
+ func(con, (ID**)&ct->tar, FALSE, userdata);
/* script */
- func(con, (ID**)&data->text, userdata);
+ func(con, (ID**)&data->text, TRUE, userdata);
}
/* Whether this approach is maintained remains to be seen (aligorith) */
@@ -2107,10 +2107,10 @@ static void actcon_id_looper (bConstraint *con, ConstraintIDFunc func, void *use
bActionConstraint *data= con->data;
/* target */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
/* action */
- func(con, (ID**)&data->act, userdata);
+ func(con, (ID**)&data->act, TRUE, userdata);
}
static int actcon_get_tars (bConstraint *con, ListBase *list)
@@ -2273,7 +2273,7 @@ static void locktrack_id_looper (bConstraint *con, ConstraintIDFunc func, void *
bLockTrackConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int locktrack_get_tars (bConstraint *con, ListBase *list)
@@ -2584,7 +2584,7 @@ static void distlimit_id_looper (bConstraint *con, ConstraintIDFunc func, void *
bDistLimitConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int distlimit_get_tars (bConstraint *con, ListBase *list)
@@ -2712,7 +2712,7 @@ static void stretchto_id_looper (bConstraint *con, ConstraintIDFunc func, void *
bStretchToConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int stretchto_get_tars (bConstraint *con, ListBase *list)
@@ -2887,7 +2887,7 @@ static void minmax_id_looper (bConstraint *con, ConstraintIDFunc func, void *use
bMinMaxConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int minmax_get_tars (bConstraint *con, ListBase *list)
@@ -3030,8 +3030,8 @@ static void rbj_id_looper (bConstraint *con, ConstraintIDFunc func, void *userda
bRigidBodyJointConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
- func(con, (ID**)&data->child, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
+ func(con, (ID**)&data->child, FALSE, userdata);
}
static int rbj_get_tars (bConstraint *con, ListBase *list)
@@ -3083,7 +3083,7 @@ static void clampto_id_looper (bConstraint *con, ConstraintIDFunc func, void *us
bClampToConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int clampto_get_tars (bConstraint *con, ListBase *list)
@@ -3268,7 +3268,7 @@ static void transform_id_looper (bConstraint *con, ConstraintIDFunc func, void *
bTransformConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int transform_get_tars (bConstraint *con, ListBase *list)
@@ -3403,10 +3403,10 @@ static bConstraintTypeInfo CTI_TRANSFORM = {
static void shrinkwrap_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
{
- bShrinkwrapConstraint *data= con->data;
+ bShrinkwrapConstraint *data = con->data;
/* target only */
- func(con, (ID**)&data->target, userdata);
+ func(con, (ID**)&data->target, FALSE, userdata);
}
static int shrinkwrap_get_tars (bConstraint *con, ListBase *list)
@@ -3571,7 +3571,7 @@ static void damptrack_id_looper (bConstraint *con, ConstraintIDFunc func, void *
bDampTrackConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int damptrack_get_tars (bConstraint *con, ListBase *list)
@@ -3717,7 +3717,7 @@ static void splineik_id_looper (bConstraint *con, ConstraintIDFunc func, void *u
bSplineIKConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int splineik_get_tars (bConstraint *con, ListBase *list)
@@ -3790,7 +3790,7 @@ static void pivotcon_id_looper (bConstraint *con, ConstraintIDFunc func, void *u
bPivotConstraint *data= con->data;
/* target only */
- func(con, (ID**)&data->tar, userdata);
+ func(con, (ID**)&data->tar, FALSE, userdata);
}
static int pivotcon_get_tars (bConstraint *con, ListBase *list)
@@ -3922,9 +3922,9 @@ static void followtrack_id_looper(bConstraint *con, ConstraintIDFunc func, void
{
bFollowTrackConstraint *data = con->data;
- func(con, (ID**)&data->clip, userdata);
- func(con, (ID**)&data->camera, userdata);
- func(con, (ID**)&data->depth_ob, userdata);
+ func(con, (ID**)&data->clip, TRUE, userdata);
+ func(con, (ID**)&data->camera, FALSE, userdata);
+ func(con, (ID**)&data->depth_ob, FALSE, userdata);
}
static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
@@ -4116,7 +4116,7 @@ static void camerasolver_id_looper(bConstraint *con, ConstraintIDFunc func, void
{
bCameraSolverConstraint *data = con->data;
- func(con, (ID**)&data->clip, userdata);
+ func(con, (ID**)&data->clip, TRUE, userdata);
}
static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
@@ -4172,8 +4172,8 @@ static void objectsolver_id_looper(bConstraint *con, ConstraintIDFunc func, void
{
bObjectSolverConstraint *data= con->data;
- func(con, (ID**)&data->clip, userdata);
- func(con, (ID**)&data->camera, userdata);
+ func(con, (ID**)&data->clip, FALSE, userdata);
+ func(con, (ID**)&data->camera, FALSE, userdata);
}
static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
@@ -4535,12 +4535,20 @@ void id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdat
/* ......... */
/* helper for copy_constraints(), to be used for making sure that ID's are valid */
-static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, void *UNUSED(userData))
+static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED(isReference), void *UNUSED(userData))
{
if (*idpoin && (*idpoin)->lib)
id_lib_extern(*idpoin);
}
+/* helper for copy_constraints(), to be used for making sure that usercounts of copied ID's are fixed up */
+static void con_fix_copied_refs_cb(bConstraint *con, ID **idpoin, short isReference, void *UNUSED(userData))
+{
+ /* increment usercount if this is a reference type */
+ if ((*idpoin) && (isReference))
+ id_us_plus(*idpoin);
+}
+
/* duplicate all of the constraints in a constraint stack */
void copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
{
@@ -4560,6 +4568,10 @@ void copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
/* perform custom copying operations if needed */
if (cti->copy_data)
cti->copy_data(con, srccon);
+
+ /* fix usercounts for all referenced data in referenced data */
+ if (cti->id_looper)
+ cti->id_looper(con, con_fix_copied_refs_cb, NULL);
/* for proxies we don't want to make extern */
if (do_extern) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 231c1ab8d03..ec7d58035b4 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2473,10 +2473,19 @@ typedef struct tConstraintLinkData {
ID *id;
} tConstraintLinkData;
/* callback function used to relink constraint ID-links */
-static void lib_link_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, void *userdata)
+static void lib_link_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, short isReference, void *userdata)
{
tConstraintLinkData *cld= (tConstraintLinkData *)userdata;
- *idpoin = newlibadr(cld->fd, cld->id->lib, *idpoin);
+
+ /* for reference types, we need to increment the usercounts on load... */
+ if (isReference) {
+ /* reference type - with usercount */
+ *idpoin = newlibadr_us(cld->fd, cld->id->lib, *idpoin);
+ }
+ else {
+ /* target type - no usercount needed */
+ *idpoin = newlibadr(cld->fd, cld->id->lib, *idpoin);
+ }
}
static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
@@ -8115,7 +8124,7 @@ typedef struct tConstraintExpandData {
Main *mainvar;
} tConstraintExpandData;
/* callback function used to expand constraint ID-links */
-static void expand_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, void *userdata)
+static void expand_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED(isReference), void *userdata)
{
tConstraintExpandData *ced= (tConstraintExpandData *)userdata;
expand_doit(ced->fd, ced->mainvar, *idpoin);
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 94ea79099c2..06352fd727c 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -837,7 +837,7 @@ void rna_def_animdata(BlenderRNA *brna)
/* Active Action */
prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
/* this flag as well as the dynamic test must be defined for this to be editable... */
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_REFCOUNT);
RNA_def_property_pointer_funcs(prop, NULL, "rna_AnimData_action_set", NULL, "rna_Action_id_poll");
RNA_def_property_editable_func(prop, "rna_AnimData_action_editable");
RNA_def_property_ui_text(prop, "Action", "Active Action for this datablock");
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index e321e83dd61..b812c574a01 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -562,7 +562,7 @@ static void rna_def_constraint_python(BlenderRNA *brna)
prop = RNA_def_property(srna, "text", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Script", "The text object that contains the Python script");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_REFCOUNT);
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
prop = RNA_def_property(srna, "use_targets", PROP_BOOLEAN, PROP_NONE);
@@ -1097,7 +1097,7 @@ static void rna_def_constraint_action(BlenderRNA *brna)
prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "act");
RNA_def_property_ui_text(prop, "Action", "The constraining action");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_REFCOUNT);
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 8d262c58f9b..7ad13b8a6d1 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -459,7 +459,7 @@ static void rna_def_nlastrip(BlenderRNA *brna)
prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "act");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Action_id_poll");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_REFCOUNT);
RNA_def_property_editable_func(prop, "rna_NlaStrip_action_editable");
RNA_def_property_ui_text(prop, "Action", "Action referenced by this strip");
RNA_def_property_update(prop, NC_ANIMATION|ND_NLA, NULL); /* this will do? */