From da6b87abb116b6e2d76c1c40aaaffbf9e14f59c9 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 19 Feb 2006 17:42:20 +0000 Subject: [PATCH] Path: [ #2789 ] Add a "copy size" constraint At long last! This new constraint is pretty simple. Following in the footsteps of such giants as Copy Loc and Copy Rot, it lets you constrain the size of an object/bone to another object/bone, with per axis restrictions. --- source/blender/blenkernel/intern/constraint.c | 70 +++++++++++++++++++ source/blender/blenloader/intern/readfile.c | 13 ++++ source/blender/blenloader/intern/writefile.c | 3 + source/blender/include/butspace.h | 1 + .../blender/makesdna/DNA_constraint_types.h | 15 +++- source/blender/src/buttons_object.c | 48 +++++++++++++ source/blender/src/editconstraint.c | 39 +++++++++-- 7 files changed, 181 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 7458a0230dd..40bdeff646c 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -181,6 +181,14 @@ void relink_constraints (struct ListBase *list) ID_NEW(data->tar); } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; case CONSTRAINT_TYPE_FOLLOWPATH: { bFollowPathConstraint *data; @@ -281,6 +289,13 @@ char constraint_has_target (bConstraint *con) return 1; } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data = con->data; + if (data->tar) + return 1; + } + break; case CONSTRAINT_TYPE_MINMAX: { bMinMaxConstraint *data = con->data; @@ -341,6 +356,12 @@ Object *get_constraint_target(bConstraint *con, char **subtarget) return data->tar; } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data = con->data; + return data->tar; + } + break; case CONSTRAINT_TYPE_KINEMATIC: { bKinematicConstraint *data = con->data; @@ -418,6 +439,13 @@ void set_constraint_target(bConstraint *con, Object *ob, char *subtarget) if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32); } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data = con->data; + data->tar= ob; + if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32); + } + break; case CONSTRAINT_TYPE_KINEMATIC: { bKinematicConstraint *data = con->data; @@ -575,6 +603,15 @@ void *new_constraint_data (short type) result = data; } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data; + data = MEM_callocN(sizeof(bLocateLikeConstraint), "sizelikeConstraint"); + + data->flag |= SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z; + result = data; + } + break; case CONSTRAINT_TYPE_ACTION: { bActionConstraint *data; @@ -890,6 +927,21 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own Mat4One (mat); } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data; + data = (bSizeLikeConstraint*)con->data; + + if (data->tar){ + /* Update the location of the target object */ + where_is_object_time (data->tar, ctime); + constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); + valid=1; + } + else + Mat4One (mat); + } + break; case CONSTRAINT_TYPE_TRACKTO: { bTrackToConstraint *data; @@ -1101,6 +1153,24 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, ob->obmat[2][2] = tmat[2][2]*size[2]; } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + float obsize[3], size[3]; + bSizeLikeConstraint *data; + + data = constraint->data; + + Mat4ToSize(targetmat, size); + Mat4ToSize(ob->obmat, obsize); + + if (data->flag & SIZELIKE_X && obsize[0] != 0) + VecMulf(ob->obmat[0], size[0] / obsize[0]); + if (data->flag & SIZELIKE_Y && obsize[1] != 0) + VecMulf(ob->obmat[1], size[1] / obsize[1]); + if (data->flag & SIZELIKE_Z && obsize[2] != 0) + VecMulf(ob->obmat[2], size[2] / obsize[2]); + } + break; case CONSTRAINT_TYPE_NULL: { } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ba532cfdfe3..a688effe8a7 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1399,6 +1399,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist) data->tar = newlibadr(fd, id->lib, data->tar); }; break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data; + data= ((bSizeLikeConstraint*)con->data); + data->tar = newlibadr(fd, id->lib, data->tar); + }; + break; case CONSTRAINT_TYPE_KINEMATIC: { bKinematicConstraint *data; @@ -5719,6 +5726,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb) expand_doit(fd, mainvar, data->tar); break; } + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data = (bSizeLikeConstraint*)curcon->data; + expand_doit(fd, mainvar, data->tar); + break; + } case CONSTRAINT_TYPE_KINEMATIC: { bKinematicConstraint *data = (bKinematicConstraint*)curcon->data; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index cb2abd71ca0..c1d8eda9007 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -647,6 +647,9 @@ static void write_constraints(WriteData *wd, ListBase *conlist) case CONSTRAINT_TYPE_LOCLIKE: writestruct(wd, DATA, "bLocateLikeConstraint", 1, con->data); break; + case CONSTRAINT_TYPE_SIZELIKE: + writestruct(wd, DATA, "bSizeLikeConstraint", 1, con->data); + break; case CONSTRAINT_TYPE_ACTION: writestruct(wd, DATA, "bActionConstraint", 1, con->data); break; diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 999213083ca..82c9756f2b3 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -591,6 +591,7 @@ enum { B_CONSTRAINT_ADD_MINMAX, B_CONSTRAINT_ADD_ROTLIKE, B_CONSTRAINT_ADD_LOCLIKE, + B_CONSTRAINT_ADD_SIZELIKE, B_CONSTRAINT_ADD_ACTION, B_CONSTRAINT_ADD_LOCKTRACK, B_CONSTRAINT_ADD_FOLLOWPATH, diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index cf1c5101407..b7dcadd501c 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -105,6 +105,13 @@ typedef struct bMinMaxConstraint{ char subtarget[32]; } bMinMaxConstraint; +typedef struct bSizeLikeConstraint{ + Object *tar; + int flag; + int reserved1; + char subtarget[32]; +} bSizeLikeConstraint; + typedef struct bActionConstraint{ Object *tar; short type; @@ -174,7 +181,7 @@ typedef struct bStretchToConstraint{ #define CONSTRAINT_TYPE_SIZELIMIT 7 /* Unimplemented */ #define CONSTRAINT_TYPE_ROTLIKE 8 #define CONSTRAINT_TYPE_LOCLIKE 9 -#define CONSTRAINT_TYPE_SIZELIKE 10 /* Unimplemented */ +#define CONSTRAINT_TYPE_SIZELIKE 10 #define CONSTRAINT_TYPE_PYTHON 11 /* Unimplemented */ #define CONSTRAINT_TYPE_ACTION 12 #define CONSTRAINT_TYPE_LOCKTRACK 13 /* New Tracking constraint that locks an axis in place - theeth */ @@ -208,6 +215,12 @@ typedef struct bStretchToConstraint{ #define LOCLIKE_Y 0x02 #define LOCLIKE_Z 0x04 #define LOCSPACE 0x08 + +/* bSizeLikeConstraint.flag */ +#define SIZELIKE_X 0x01 +#define SIZELIKE_Y 0x02 +#define SIZELIKE_Z 0x04 +#define SIZESPACE 0x08 /* Axis flags */ #define LOCK_X 0x00 diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index a6906af245d..9f43e06926c 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -334,6 +334,9 @@ static void get_constraint_typestring (char *str, bConstraint *con) case CONSTRAINT_TYPE_LOCLIKE: strcpy (str, "Copy Location"); return; + case CONSTRAINT_TYPE_SIZELIKE: + strcpy (str, "Copy Size"); + return; case CONSTRAINT_TYPE_ACTION: strcpy (str, "Action"); return; @@ -367,6 +370,8 @@ static int get_constraint_col(bConstraint *con) return TH_BUT_POPUP; case CONSTRAINT_TYPE_MINMAX: return TH_BUT_POPUP; + case CONSTRAINT_TYPE_SIZELIKE: + return TH_BUT_POPUP; case CONSTRAINT_TYPE_ACTION: return TH_BUT_ACTION; case CONSTRAINT_TYPE_LOCKTRACK: @@ -686,6 +691,38 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s uiBlockEndAlign(block); } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data = con->data; + bArmature *arm; + height = 66; + + BIF_ThemeColor(curCol); + glRects(*xco+3, *yco-height-39, *xco+width+30, *yco-18); + + uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); + + /* Draw target parameters */ + uiBlockBeginAlign(block); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); + + arm = get_armature(data->tar); + if (arm){ + but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone"); + uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar); + } + else + strcpy (data->subtarget, ""); + uiBlockEndAlign(block); + + /* Draw XYZ toggles */ + uiBlockBeginAlign(block); + but=uiDefButI(block, TOG|BIT|0, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component"); + but=uiDefButI(block, TOG|BIT|1, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component"); + but=uiDefButI(block, TOG|BIT|2, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component"); + uiBlockEndAlign(block); + } + break; case CONSTRAINT_TYPE_KINEMATIC: { bKinematicConstraint *data = con->data; @@ -977,6 +1014,7 @@ static uiBlock *add_constraintmenu(void *arg_unused) uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIKE,"Copy Location", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, ""); uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIKE,"Copy Rotation", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SIZELIKE,"Copy Size", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -1083,6 +1121,16 @@ void do_constraintbuts(unsigned short event) BIF_undo_push("Add constraint"); } break; + case B_CONSTRAINT_ADD_SIZELIKE: + { + bConstraint *con; + + con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE); + add_constraint_to_active(ob, con); + + BIF_undo_push("Add constraint"); + } + break; case B_CONSTRAINT_ADD_ACTION: { bConstraint *con; diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c index a85f0dd835d..b3f2ac07c0b 100644 --- a/source/blender/src/editconstraint.c +++ b/source/blender/src/editconstraint.c @@ -266,6 +266,12 @@ char *get_con_subtarget_name(bConstraint *con, Object *target) if (data->tar==target) return data->subtarget; } break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data = con->data; + if (data->tar==target) return data->subtarget; + } + break; case CONSTRAINT_TYPE_KINEMATIC: { bKinematicConstraint *data = con->data; @@ -428,6 +434,24 @@ static void test_constraints (Object *owner, const char* substring) break; } + if ( (data->tar == owner) && + (!get_named_bone(get_armature(owner), + data->subtarget))) { + curcon->flag |= CONSTRAINT_DISABLE; + break; + } + } + break; + case CONSTRAINT_TYPE_SIZELIKE: + { + bSizeLikeConstraint *data = curcon->data; + + if (!exist_object(data->tar)){ + data->tar = NULL; + curcon->flag |= CONSTRAINT_DISABLE; + break; + } + if ( (data->tar == owner) && (!get_named_bone(get_armature(owner), data->subtarget))) { @@ -629,21 +653,21 @@ void add_constraint(int only_IK) else { if(pchanact) { if(pchansel) - nr= pupmenu("Add Constraint to Active Bone%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7"); + nr= pupmenu("Add Constraint to Active Bone%t|Copy Location%x1|Copy Rotation%x2|Copy Size%x8|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7"); else if(obsel && obsel->type==OB_CURVE) - nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Stretch To%x7"); + nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Size%x8|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Stretch To%x7"); else if(obsel) - nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7"); + nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Size%x8|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7"); else - nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7"); + nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Size%x8|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7"); } else { if(obsel && obsel->type==OB_CURVE) - nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6"); + nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Size%x8|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6"); else if(obsel) - nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5"); + nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Size%x8|Track To%x3|Floor%x4|Locked Track%x5"); else - nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5"); + nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Size%x8|Track To%x3|Floor%x4|Locked Track%x5"); } } @@ -689,6 +713,7 @@ void add_constraint(int only_IK) else if(nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK); else if(nr==6) con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH); else if(nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO); + else if(nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE); if(con==NULL) return; /* paranoia */