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
path: root/source
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2008-01-04 14:21:50 +0300
committerJoshua Leung <aligorith@gmail.com>2008-01-04 14:21:50 +0300
commit5e58f5d4635dd4d4b38434643df5ede17f0e103f (patch)
treed4a2eef983a7dea9fb99fc952d3fea28973aa331 /source
parent56faf73e3c914972effd12be1f26b1b7602a5de0 (diff)
== Local Constraints for Proxies (Peach Request) ==
Proxy protected bones can now get local (per-file) constraints added to them, which will be preserved after a file load. This is necessary for adding constraints to proxy-protected bones for special purposes while animating (i.e. adding CopyLocs to IK-hand controls to pick up an object). These must be added after any constraints from the proxy, as proxy constraints may come and go without warning. As such, the UI forbids this from happening by removing the relevant button. I've also made UI-changes to show which constraints come from the proxy (the buttons to move the constraint up/down and delete it, are replace with two icons - a the proxy 'ghost' icon and a lock). Also, trying to change any settings of proxy-protected constraint will show an error. Notes: * Object constraints are still not playing nice with proxies yet. They didn't before this commit either...
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_constraint.h4
-rw-r--r--source/blender/blenkernel/intern/armature.c10
-rw-r--r--source/blender/blenkernel/intern/constraint.c40
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h4
-rw-r--r--source/blender/src/buttons_object.c98
-rw-r--r--source/blender/src/editconstraint.c31
-rw-r--r--source/blender/src/poseobject.c3
7 files changed, 150 insertions, 40 deletions
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index aa8e9cf18f8..5d145dc6dee 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -117,6 +117,9 @@ void copy_constraints(struct ListBase *dst, struct ListBase *src);
void relink_constraints(struct ListBase *list);
void free_constraint_data(struct bConstraint *con);
+/* Constraints + Proxies function prototypes */
+void extract_proxylocal_constraints(struct ListBase *dst, struct ListBase *src);
+short proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pchan);
/* Constraint Channel function prototypes */
struct bConstraintChannel *get_constraint_channel(struct ListBase *list, const char *name);
@@ -126,6 +129,7 @@ void copy_constraint_channels(struct ListBase *dst, struct ListBase *src);
void clone_constraint_channels(struct ListBase *dst, struct ListBase *src);
void free_constraint_channels(struct ListBase *chanbase);
+
/* Constraint Evaluation function prototypes */
struct bConstraintOb *constraints_make_evalob(struct Object *ob, void *subdata, short datatype);
void constraints_clear_evalob(struct bConstraintOb *cob);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 6bdb663545c..f4da821e3ea 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1317,6 +1317,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
pchan= pose->chanbase.first;
for(; pchan; pchan= pchan->next) {
if(pchan->bone->layer & layer_protected) {
+ ListBase proxylocal_constraints = {NULL, NULL};
pchanp= get_pose_channel(frompose, pchan->name);
/* copy posechannel to temp, but restore important pointers */
@@ -1327,9 +1328,16 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
pchanw.child= pchan->child;
pchanw.path= NULL;
- /* constraints, set target ob pointer to own object */
+ /* constraints - proxy constraints are flushed... local ones are added after
+ * 1. extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints
+ * 2. copy proxy-pchan's constraints on-to new
+ * 3. add extracted local constraints back on top
+ */
+ extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints);
copy_constraints(&pchanw.constraints, &pchanp->constraints);
+ addlisttolist(&pchanw.constraints, &proxylocal_constraints);
+ /* constraints - set target ob pointer to own object */
for (con= pchanw.constraints.first; con; con= con->next) {
bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index c87c75b0190..295c52f1415 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -3246,6 +3246,46 @@ void copy_constraints (ListBase *dst, ListBase *src)
}
}
+/* -------- Constraints and Proxies ------- */
+
+/* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL (i.e. added to bone that's proxy-synced in this file) */
+void extract_proxylocal_constraints (ListBase *dst, ListBase *src)
+{
+ bConstraint *con, *next;
+
+ /* for each tagged constraint, remove from src and move to dst */
+ for (con= src->first; con; con= next) {
+ next= con->next;
+
+ /* check if tagged */
+ if (con->flag & CONSTRAINT_PROXY_LOCAL) {
+ BLI_remlink(src, con);
+ BLI_addtail(dst, con);
+ }
+ }
+}
+
+/* Returns if the owner of the constraint is proxy-protected */
+short proxylocked_constraints_owner (Object *ob, bPoseChannel *pchan)
+{
+ /* Currently, constraints can only be on object or bone level */
+ if (ob && ob->proxy) {
+ if (ob->pose && pchan) {
+ bArmature *arm= ob->data;
+
+ /* On bone-level, check if bone is on proxy-protected layer */
+ if ((pchan->bone) && (pchan->bone->layer & arm->layer_protected))
+ return 1;
+ }
+ else {
+ /* FIXME: constraints on object-level are not handled well yet */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* -------- Target-Matrix Stuff ------- */
/* This function is a relic from the prior implementations of the constraints system, when all
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 7f9fa49e7a9..4ae8d6b39e6 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -352,7 +352,9 @@ typedef enum B_CONSTRAINT_FLAG {
/* to indicate that the owner's space should only be changed into ownspace, but not out of it */
CONSTRAINT_SPACEONCE = (1<<6),
/* influence ipo is on constraint itself, not in action channel */
- CONSTRAINT_OWN_IPO = (1<<7)
+ CONSTRAINT_OWN_IPO = (1<<7),
+ /* indicates that constraint was added locally (i.e. didn't come from the proxy-lib) */
+ CONSTRAINT_PROXY_LOCAL = (1<<8)
} B_CONSTRAINT_FLAG;
/* bConstraint->ownspace/tarspace */
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 243681bc800..66cd59d1751 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -190,15 +190,18 @@ static void constraint_active_func(void *ob_v, void *con_v)
static void add_constraint_to_active(Object *ob, bConstraint *con)
{
- ListBase *list;
+ ListBase *list= get_active_constraints(ob);
+ bPoseChannel *pchan= get_active_posechannel(ob);
- list = get_active_constraints(ob);
if (list) {
unique_constraint_name(con, list);
BLI_addtail(list, con);
+ if (proxylocked_constraints_owner(ob, pchan))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+
con->flag |= CONSTRAINT_ACTIVE;
- for(con= con->prev; con; con= con->prev)
+ for (con= con->prev; con; con= con->prev)
con->flag &= ~CONSTRAINT_ACTIVE;
}
}
@@ -209,8 +212,7 @@ static void get_constraint_ipo_context(void *ob_v, char *actname)
{
Object *ob= ob_v;
- /* todo; check object if it has ob-level action ipo */
-
+ /* todo: check object if it has ob-level action ipo */
if (ob->flag & OB_POSEMODE) {
bPoseChannel *pchan;
@@ -503,12 +505,15 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short
static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, short *xco, short *yco)
{
Object *ob= OBACT;
+ bPoseChannel *pchan= get_active_posechannel(ob);
bConstraintTypeInfo *cti;
uiBut *but;
char typestr[32];
short height, width = 265;
+ short proxy_protected;
int rb_col;
+ /* get constraint typeinfo */
cti= constraint_get_typeinfo(con);
if (cti == NULL) {
/* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
@@ -520,6 +525,13 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
else
strcpy(typestr, cti->name);
+ /* determine whether constraint is proxy protected or not */
+ if (proxylocked_constraints_owner(ob, pchan)) {
+ proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
+ }
+ else
+ proxy_protected= 0;
+
/* unless button has own callback, it adds this callback to button */
uiBlockSetFunc(block, constraint_active_func, ob, con);
@@ -534,17 +546,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* open/close */
uiDefIconButBitS(block, ICONTOG, CONSTRAINT_EXPAND, B_CONSTRAINT_TEST, ICON_DISCLOSURE_TRI_RIGHT, *xco-10, *yco, 20, 20, &con->flag, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Constraint");
- /* up/down */
- uiBlockBeginAlign(block);
- uiBlockSetEmboss(block, UI_EMBOSS);
- but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
- uiButSetFunc(but, constraint_moveUp, ob, con);
-
- but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
- uiButSetFunc(but, constraint_moveDown, ob, con);
- uiBlockEndAlign(block);
-
- if (con->flag & CONSTRAINT_EXPAND) {
+ /* name */
+ if ((con->flag & CONSTRAINT_EXPAND) && (proxy_protected==0)) {
if (con->flag & CONSTRAINT_DISABLE)
uiBlockSetCol(block, TH_REDALERT);
@@ -568,14 +571,60 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiBlockSetCol(block, TH_AUTO);
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
+ if (proxy_protected) {
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
+ uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, *xco+244, *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
+ uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, *xco+262, *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+ else {
+ short prev_proxylock;
+
+ /* Up/Down buttons:
+ * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
+ * as that poses problems when restoring them, so disable the "up" button where
+ * it may cause this situation.
+ */
+ if (proxylocked_constraints_owner(ob, pchan)) {
+ if (con->prev) {
+ prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
+ }
+ else
+ prev_proxylock= 0;
+ }
+ else
+ prev_proxylock= 0;
+
+ uiBlockBeginAlign(block);
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ if (prev_proxylock == 0) {
+ but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
+ uiButSetFunc(but, constraint_moveUp, ob, con);
+ }
+
+ but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
+ uiButSetFunc(but, constraint_moveDown, ob, con);
+ uiBlockEndAlign(block);
+
+
+ /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ but = uiDefIconBut(block, BUT, B_CONSTRAINT_CHANGETARGET, ICON_X, *xco+262, *yco, 19, 19, list, 0.0, 0.0, 0.0, 0.0, "Delete constraint");
+ uiButSetFunc(but, del_constraint_func, ob, con);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+
+ /* Set but-locks for protected settings (magic numbers are used here!) */
+ if (proxy_protected)
+ uiSetButLock(1, "Cannot edit Proxy-Protected Constraint");
- but = uiDefIconBut(block, BUT, B_CONSTRAINT_CHANGETARGET, ICON_X, *xco+262, *yco, 19, 19, list, 0.0, 0.0, 0.0, 0.0, "Delete constraint");
- uiButSetFunc(but, del_constraint_func, ob, con);
-
- uiBlockSetEmboss(block, UI_EMBOSS);
-
-
/* Draw constraint data */
if ((con->flag & CONSTRAINT_EXPAND) == 0) {
(*yco) -= 21;
@@ -1649,6 +1698,9 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
else {
(*yco)-=3;
}
+
+ /* clear any locks set up for proxies/lib-linking */
+ uiClearButLock();
}
static uiBlock *add_constraintmenu(void *arg_unused)
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c
index e0588b4c2a0..940634290bd 100644
--- a/source/blender/src/editconstraint.c
+++ b/source/blender/src/editconstraint.c
@@ -247,6 +247,9 @@ void add_constraint_to_object(bConstraint *con, Object *ob)
unique_constraint_name(con, list);
BLI_addtail(list, con);
+ if (proxylocked_constraints_owner(ob, NULL))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+
con->flag |= CONSTRAINT_ACTIVE;
for (con= con->prev; con; con= con->prev)
con->flag &= ~CONSTRAINT_ACTIVE;
@@ -258,7 +261,6 @@ void add_constraint_to_object(bConstraint *con, Object *ob)
*/
static void test_constraints (Object *owner, const char substring[])
{
-
bConstraint *curcon;
ListBase *conlist= NULL;
int type;
@@ -266,8 +268,6 @@ static void test_constraints (Object *owner, const char substring[])
if (owner==NULL) return;
/* Check parents */
- /* Get the constraint list for this object */
-
if (strlen (substring)) {
switch (owner->type) {
case OB_ARMATURE:
@@ -281,7 +281,7 @@ static void test_constraints (Object *owner, const char substring[])
else
type = CONSTRAINT_OBTYPE_OBJECT;
-
+ /* Get the constraint list for this object */
switch (type) {
case CONSTRAINT_OBTYPE_OBJECT:
conlist = &owner->constraints;
@@ -656,12 +656,6 @@ void add_constraint(int only_IK)
/* find active channel */
pchanact= get_active_posechannel(ob);
if(pchanact==NULL) return;
-
- /* check protection */
- if(ob->proxy && (pchanact->bone->layer & arm->layer_protected)) {
- error("Bone is Proxy protected");
- return;
- }
/* find selected bone */
for(pchansel= ob->pose->chanbase.first; pchansel; pchansel= pchansel->next) {
@@ -745,8 +739,11 @@ void add_constraint(int only_IK)
con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
BLI_addtail(&pchanact->constraints, con);
unique_constraint_name(con, &pchanact->constraints);
- pchanact->constflag |= PCHAN_HAS_IK; // for draw, but also for detecting while pose solving
- if(nr==11) pchanact->constflag |= PCHAN_HAS_TARGET;
+ pchanact->constflag |= PCHAN_HAS_IK; /* for draw, but also for detecting while pose solving */
+ if (nr==11)
+ pchanact->constflag |= PCHAN_HAS_TARGET;
+ if (proxylocked_constraints_owner(ob, pchanact))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
}
else {
@@ -812,10 +809,14 @@ void add_constraint(int only_IK)
BLI_addtail(&pchanact->constraints, con);
unique_constraint_name(con, &pchanact->constraints);
pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
+ if (proxylocked_constraints_owner(ob, pchanact))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
}
else {
BLI_addtail(&ob->constraints, con);
unique_constraint_name(con, &ob->constraints);
+ if (proxylocked_constraints_owner(ob, NULL))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
}
}
@@ -867,9 +868,9 @@ void add_constraint(int only_IK)
else
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); // and all its relations
- allqueue (REDRAWVIEW3D, 0);
- allqueue (REDRAWBUTSOBJECT, 0);
- allqueue (REDRAWOOPS, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSOBJECT, 0);
+ allqueue(REDRAWOOPS, 0);
if (only_IK)
BIF_undo_push("Add IK Constraint");
diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c
index 585ff320b71..e1854c0043e 100644
--- a/source/blender/src/poseobject.c
+++ b/source/blender/src/poseobject.c
@@ -165,6 +165,9 @@ bPoseChannel *get_active_posechannel (Object *ob)
bArmature *arm= ob->data;
bPoseChannel *pchan;
+ if ELEM(NULL, ob, ob->pose)
+ return NULL;
+
/* find active */
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
if(pchan->bone && (pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer))