diff options
-rw-r--r-- | source/blender/blenkernel/BKE_constraint.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 40 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_constraint_types.h | 4 | ||||
-rw-r--r-- | source/blender/src/buttons_object.c | 98 | ||||
-rw-r--r-- | source/blender/src/editconstraint.c | 31 | ||||
-rw-r--r-- | source/blender/src/poseobject.c | 3 |
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)) |