Stretch To constraint
authorMartin Poirier <theeth@yahoo.com>
Sun, 5 Sep 2004 20:21:16 +0000 (20:21 +0000)
committerMartin Poirier <theeth@yahoo.com>
Sun, 5 Sep 2004 20:21:16 +0000 (20:21 +0000)
Read today's meeting minutes for a description.

Bjornmose: We'll need some example and screenshots for the dev pages of blender3d.org. If you can do some, neat, if not, I'll do them.

Matt, Emilie and Chris: Please review UI addition. Pixel alignement and all that fun stuff has not be overly looked for (though I did some cleaning by adding alignment blocks).

source/blender/blenkernel/intern/constraint.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/butspace.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/src/buttons_object.c
source/blender/src/editconstraint.c

index e590dd1dc24702afba1c3f16725adfd74afce663..221847de6bfa12c3ffa890539868add041e8c7fd 100644 (file)
@@ -122,6 +122,12 @@ char constraint_has_target (bConstraint *con) {
                        if (data->tar)
                                return 1;
                }
+       case CONSTRAINT_TYPE_STRETCHTO:
+               {
+                       bStretchToConstraint *data = con->data;
+                       if (data->tar)
+                               return 1;
+               }
                break;
        }
        // Unknown types or CONSTRAINT_TYPE_NULL or no target
@@ -130,54 +136,59 @@ char constraint_has_target (bConstraint *con) {
 
 Object *get_constraint_target(bConstraint *con)
 {
-       /*
-        * If the target for this constraint is target, return a pointer 
-        * to the name for this constraints subtarget ... NULL otherwise
-        */
+/*
+* If the target for this constraint is target, return a pointer 
+* to the name for this constraints subtarget ... NULL otherwise
+       */
        switch (con->type) {
-
-               case CONSTRAINT_TYPE_ACTION:
+       case CONSTRAINT_TYPE_ACTION:
                {
                        bActionConstraint *data = con->data;
                        return data->tar;
                }
                break;
-               case CONSTRAINT_TYPE_LOCLIKE:
+       case CONSTRAINT_TYPE_LOCLIKE:
                {
                        bLocateLikeConstraint *data = con->data;
                        return data->tar;
                }
                break;
-               case CONSTRAINT_TYPE_ROTLIKE:
+       case CONSTRAINT_TYPE_ROTLIKE:
                {
                        bRotateLikeConstraint *data = con->data;
                        return data->tar;
                }
                break;
-               case CONSTRAINT_TYPE_KINEMATIC:
+       case CONSTRAINT_TYPE_KINEMATIC:
                {
                        bKinematicConstraint *data = con->data;
                        return data->tar;
                }
                break;
-               case CONSTRAINT_TYPE_TRACKTO:
+       case CONSTRAINT_TYPE_TRACKTO:
                {
                        bTrackToConstraint *data = con->data;
                        return data->tar;
                }
                break;
-               case CONSTRAINT_TYPE_LOCKTRACK:
+       case CONSTRAINT_TYPE_LOCKTRACK:
                {
                        bLockTrackConstraint *data = con->data;
                        return data->tar;
                }
                break;
-               case CONSTRAINT_TYPE_FOLLOWPATH: 
+       case CONSTRAINT_TYPE_FOLLOWPATH: 
                {
                        bFollowPathConstraint *data = con->data;
                        return data->tar;
                }
                break;
+       case CONSTRAINT_TYPE_STRETCHTO:
+               {
+                       bStretchToConstraint *data = con->data;
+                       return (data->tar);
+               }
+               break;
        }
        
        return NULL;  
@@ -310,6 +321,18 @@ void       *new_constraint_data (short type)
                        result = data;
                }
                break;
+       case CONSTRAINT_TYPE_STRETCHTO:
+               {
+                       bStretchToConstraint *data;
+                       data = MEM_callocN(sizeof(bStretchToConstraint), "StretchToConstraint");
+
+                       data->volmode = 0;
+                       data->plane = 0;
+                       data->orglength = 0.0; 
+                       data->bulge = 1.0;
+                       result = data;
+               }
+               break; 
        default:
                result = NULL;
                break;
@@ -722,6 +745,21 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                                Mat4One (mat);
                }
                break;
+       case CONSTRAINT_TYPE_STRETCHTO:
+               {
+                       bStretchToConstraint *data;
+                       data = (bStretchToConstraint*)con->data;
+
+                       if (data->tar){
+                               where_is_object_time (data->tar, ctime);        
+                               constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+                               valid = 1;
+                       }
+                       else
+                               Mat4One (mat);
+               }
+               break;
+
        default:
                Mat4One(mat);
                break;
@@ -796,6 +834,15 @@ void relink_constraints (struct ListBase *list)
                                ID_NEW(data->tar);
                        }
                        break;
+               case CONSTRAINT_TYPE_STRETCHTO:
+                       {
+                               bStretchToConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                       break;
+                       
                }
        }
 }
@@ -907,6 +954,14 @@ void copy_constraints (ListBase *dst, ListBase *src)
                                data = (bFollowPathConstraint*) con->data;
                        }
                        break;
+               case CONSTRAINT_TYPE_STRETCHTO:
+                       {
+                               bStretchToConstraint *data;
+                               
+                               con->data = MEM_dupallocN (con->data);
+                               data = (bStretchToConstraint*) con->data;
+                       }
+                       break;
                default:
                        con->data = MEM_dupallocN (con->data);
                        break;
@@ -1427,6 +1482,123 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                        }
                }
                break;
+       case CONSTRAINT_TYPE_STRETCHTO:
+               {
+                       bStretchToConstraint *data;
+                       float scale[3],vec[3],xx[3],zz[3],orth[3];
+                       float totmat[3][3];
+                       float tmat[4][4];
+                       float dist;
+                       data=(bStretchToConstraint*)constraint->data;                   
+                       
+                       if (data->tar){
+                                       
+                               /* store X orientation before destroying obmat */
+                               xx[0] = ob->obmat[0][0];
+                               xx[1] = ob->obmat[0][1];
+                               xx[2] = ob->obmat[0][2];
+                               Normalise(xx);
+
+                               /* store Z orientation before destroying obmat */
+                               zz[0] = ob->obmat[2][0];
+                               zz[1] = ob->obmat[2][1];
+                               zz[2] = ob->obmat[2][2];
+                               Normalise(zz);
+
+                               dist = VecLenf( ob->obmat[3], targetmat[3]);
+
+                               if (data->orglength == 0)  data->orglength = dist;
+                               if (data->bulge ==0) data->bulge = 1.0;
+
+                               scale[1] = dist/data->orglength;
+                               switch (data->volmode){
+                               /* volume preserving scaling */
+                               case VOLUME_XZ :
+                                       scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
+                                       scale[2] = scale[0];
+                                       break;
+                               case VOLUME_X:
+                                       scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
+                                       scale[2] = 1.0;
+                                       break;
+                               case VOLUME_Z:
+                                       scale[0] = 1.0;
+                                       scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
+                                       break;
+                                       /* don't care for volume */
+                               case NO_VOLUME:
+                                       scale[0] = 1.0;
+                                       scale[2] = 1.0;
+                                       break;
+                               default: /* should not happen, but in case*/ 
+                                       return; 
+                               } /* switch (data->volmode) */
+
+                               /* Clear the object's rotation and scale */
+                               ob->obmat[0][0]=ob->size[0]*scale[0];
+                               ob->obmat[0][1]=0;
+                               ob->obmat[0][2]=0;
+                               ob->obmat[1][0]=0;
+                               ob->obmat[1][1]=ob->size[1]*scale[1];
+                               ob->obmat[1][2]=0;
+                               ob->obmat[2][0]=0;
+                               ob->obmat[2][1]=0;
+                               ob->obmat[2][2]=ob->size[2]*scale[2];
+                               
+                               VecSubf(vec, ob->obmat[3], targetmat[3]);
+                               Normalise(vec);
+                               /* new Y aligns  object target connection*/
+                               totmat[1][0] = -vec[0];
+                               totmat[1][1] = -vec[1];
+                               totmat[1][2] = -vec[2];
+                               switch (data->plane){
+                               case PLANE_X:
+                                       /* build new Z vector */
+                                       /* othogonal to "new Y" "old X! plane */
+                                       Crossf(orth, vec, xx);
+                                       Normalise(orth);
+                                       
+                                       /* new Z*/
+                                       totmat[2][0] = orth[0];
+                                       totmat[2][1] = orth[1];
+                                       totmat[2][2] = orth[2];
+                                       
+                                       /* we decided to keep X plane*/
+                                       Crossf(xx,orth, vec);
+                                       Normalise(xx);
+                                       totmat[0][0] = xx[0];
+                                       totmat[0][1] = xx[1];
+                                       totmat[0][2] = xx[2];
+                                       break;
+                               case PLANE_Z:
+                                       /* build new X vector */
+                                       /* othogonal to "new Y" "old Z! plane */
+                                       Crossf(orth, vec, zz);
+                                       Normalise(orth);
+                                       
+                                       /* new X*/
+                                       totmat[0][0] = -orth[0];
+                                       totmat[0][1] = -orth[1];
+                                       totmat[0][2] = -orth[2];
+                                       
+                                       /* we decided to keep Z */
+                                       Crossf(zz,orth, vec);
+                                       Normalise(zz);
+                                       totmat[2][0] = zz[0];
+                                       totmat[2][1] = zz[1];
+                                       totmat[2][2] = zz[2];
+                                       break;
+                               } /* switch (data->plane) */
+                               
+
+                               Mat4CpyMat4(tmat, ob->obmat);
+                               
+                               Mat4MulMat34(ob->obmat, totmat, tmat);
+
+                       }
+               }
+               break;
+       
        default:
                printf ("Error: Unknown constraint type\n");
                break;
index 498b84abb2ceb35163cc115362d7d517258d682b..1e9b7aa8e991c6ae6b08411f75df8d19f5469b8a 100644 (file)
@@ -1347,6 +1347,14 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                data->tar = newlibadr(fd, id->lib, data->tar);
                        };
                        break;
+               case CONSTRAINT_TYPE_STRETCHTO:
+                       {
+                               bStretchToConstraint *data;
+                               data= ((bStretchToConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       };
+                       break;
+
                case CONSTRAINT_TYPE_NULL:
                        break;
                }
@@ -4805,6 +4813,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
                                expand_doit(fd, mainvar, data->tar);
                                break;
                        }
+               case CONSTRAINT_TYPE_STRETCHTO:
+                       {
+                               bStretchToConstraint *data = (bStretchToConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
+                               break;
+                       }
                case CONSTRAINT_TYPE_NULL:
                        break;
                default:
index 6d84c120422598eca90be59ad1a9cdc007df692b..159b1e7a11f628512d7a40f4f8d9e3ba8cfef89e 100644 (file)
@@ -603,6 +603,9 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
                case CONSTRAINT_TYPE_FOLLOWPATH:
                        writestruct(wd, DATA, "bFollowPathConstraint", 1, con->data);
                        break;
+               case CONSTRAINT_TYPE_STRETCHTO:
+                       writestruct(wd, DATA, "bStretchToConstraint", 1, con->data);
+                       break;
                default:
                        break;
                }
index 878f94910525ed6b14a6782b4f2fd220ac25f4c6..54af18adfb337620d0474addb88cb5a4d3543180 100644 (file)
@@ -520,7 +520,9 @@ enum {
        B_CONSTRAINT_ADD_ACTION,
        B_CONSTRAINT_ADD_LOCKTRACK,
        B_CONSTRAINT_ADD_FOLLOWPATH,
-       B_CONSTRAINT_ADD_DISTANCELIMIT
+       B_CONSTRAINT_ADD_DISTANCELIMIT,
+       B_CONSTRAINT_ADD_STRETCHTO
+
 };
 
 /* *********************** */
index b4b380a6a2e2e5d37cd64f2af42d1c4921b9f67c..06a7844b785a2f668f48d9587a6af266bf0e8d0a 100644 (file)
@@ -144,6 +144,15 @@ typedef struct bRotationConstraint{
        float zmin, zmax;
 } bRotationConstraint;
 
+/* Stretch to constraint */
+typedef struct bStretchToConstraint{
+       Object          *tar;
+       int                     volmode; 
+       int         plane;
+       float           orglength;
+       float           bulge;
+       char            subtarget[32];
+} bStretchToConstraint;
 
 
 /* bConstraint.type */
@@ -185,23 +194,7 @@ typedef struct bRotationConstraint{
 #define LOCLIKE_Z              0x00000004
 #define LOCSPACE               0x00000008
 
-/* Tracking flags */
-#define LOCK_X         0x00000000
-#define LOCK_Y         0x00000001
-#define LOCK_Z         0x00000002
-
-#define UP_X           0x00000000
-#define UP_Y           0x00000001
-#define UP_Z           0x00000002
-
-#define TRACK_X                0x00000000
-#define TRACK_Y                0x00000001
-#define TRACK_Z                0x00000002
-#define TRACK_nX       0x00000003
-#define TRACK_nY       0x00000004
-#define TRACK_nZ       0x00000005
-
-/* Tracking flags */
+/* Axis flags */
 #define LOCK_X         0x00000000
 #define LOCK_Y         0x00000001
 #define LOCK_Z         0x00000002
@@ -217,21 +210,14 @@ typedef struct bRotationConstraint{
 #define TRACK_nY       0x00000004
 #define TRACK_nZ       0x00000005
 
-/* Tracking flags */
-#define LOCK_X         0x00000000
-#define LOCK_Y         0x00000001
-#define LOCK_Z         0x00000002
+#define VOLUME_XZ      0x00000000
+#define VOLUME_X       0x00000001
+#define VOLUME_Z       0x00000002
+#define NO_VOLUME      0x00000003
 
-#define UP_X           0x00000000
-#define UP_Y           0x00000001
-#define UP_Z           0x00000002
-
-#define TRACK_X                0x00000000
-#define TRACK_Y                0x00000001
-#define TRACK_Z                0x00000002
-#define TRACK_nX       0x00000003
-#define TRACK_nY       0x00000004
-#define TRACK_nZ       0x00000005
+#define PLANE_X                0x00000000
+#define PLANE_Y                0x00000001
+#define PLANE_Z                0x00000002
 
 #endif
 
index 0708fea0b13495bef8024144cba2258e6bca9f9d..ecb23733523f148517c3f2d8ffb499bd2fd39655 100644 (file)
@@ -290,6 +290,9 @@ static void get_constraint_typestring (char *str, bConstraint *con)
        case CONSTRAINT_TYPE_FOLLOWPATH:
                strcpy (str, "Follow Path");
                return;
+       case CONSTRAINT_TYPE_STRETCHTO:
+               strcpy (str, "Stretch To");
+               return;
        default:
                strcpy (str, "Unknown");
                return;
@@ -315,6 +318,8 @@ static int get_constraint_col(bConstraint *con)
                return TH_BUT_SETTING;
        case CONSTRAINT_TYPE_FOLLOWPATH:
                return TH_BUT_SETTING2;
+       case CONSTRAINT_TYPE_STRETCHTO:
+               return TH_BUT_SETTING;
        default:
                return TH_REDALERT;
        }
@@ -524,7 +529,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                        strcpy (data->subtarget, "");
                                uiBlockEndAlign(block);
        
-                               uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Tolerance:", *xco+((width/2)-117), *yco-64, 120, 18, &data->tolerance, 0.0001, 1.0, 0.0, 0.0, "Maximum distance to target after solving"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Tolerance:", *xco+((width/2)-117), *yco-64, 120, 18, &data->tolerance, 0.0001f, 1.0, 0.0, 0.0, "Maximum distance to target after solving"); 
                                uiDefButI(block, NUM, B_CONSTRAINT_REDRAW, "Iterations:", *xco+((width/2)+3), *yco-64, 120, 18, &data->iterations, 1, 10000, 0.0, 0.0, "Maximum number of solving iterations"); 
                                
                        }
@@ -656,6 +661,54 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                uiBlockEndAlign(block);
                        }
                        break;
+               case CONSTRAINT_TYPE_STRETCHTO:
+                       {
+                               bStretchToConstraint *data = con->data;
+                               bArmature *arm;
+                               height = 105;
+                               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, 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");
+                               }
+                               else
+                                       strcpy (data->subtarget, "");
+                               uiBlockEndAlign(block);
+
+                               
+                               uiBlockBeginAlign(block);
+                               uiDefButF(block,BUTM,B_CONSTRAINT_REDRAW,"R",*xco, *yco-60,20,18,&(data->orglength),0.0,0,0,0,"Recalculate RLenght");
+                               uiDefButF(block,NUM,B_CONSTRAINT_REDRAW,"Rest Length:",*xco+20, *yco-60,237,18,&(data->orglength),0.0,100,0.5,0.5,"Lenght at Rest Position");
+                               uiBlockEndAlign(block);
+
+                               uiDefButF(block,NUM,B_CONSTRAINT_REDRAW,"Volume Variation:",*xco+20, *yco-82,237,18,&(data->bulge),0.0,100,0.5,0.5,"Factor between volume variation and stretching");
+
+                               uiBlockBeginAlign(block);
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Vol:",*xco+12, *yco-104,30,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               uiDefButI(block, ROW,B_CONSTRAINT_REDRAW,"XZ",   *xco+42, *yco-104,30,18, &data->volmode, 12.0, 0.0, 0, 0, "Keep Volume: Scaling X & Z");
+                               uiDefButI(block, ROW,B_CONSTRAINT_REDRAW,"X",    *xco+72, *yco-104,20,18, &data->volmode, 12.0, 1.0, 0, 0, "Keep Volume: Scaling X");
+                               uiDefButI(block, ROW,B_CONSTRAINT_REDRAW,"Z",    *xco+92, *yco-104,20,18, &data->volmode, 12.0, 2.0, 0, 0, "Keep Volume: Scaling Z");
+                               uiDefButI(block, ROW,B_CONSTRAINT_REDRAW,"NONE", *xco+112, *yco-104,50,18, &data->volmode, 12.0, 3.0, 0, 0, "Ignore Volume");
+                               uiBlockEndAlign(block);
+
+                               
+                               uiBlockBeginAlign(block);
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Plane:",*xco+170, *yco-104,40,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               uiDefButI(block, ROW,B_CONSTRAINT_REDRAW,"X",     *xco+210, *yco-104,20,18, &data->plane, 12.0, 0.0, 0, 0, "Keep X axis");
+                               uiDefButI(block, ROW,B_CONSTRAINT_REDRAW,"Z",     *xco+230, *yco-104,20,18, &data->plane, 12.0, 2.0, 0, 0, "Keep Z axis");
+                               uiBlockEndAlign(block);
+                               }
+                       break;
                case CONSTRAINT_TYPE_NULL:
                        {
                                height = 17;
@@ -711,6 +764,10 @@ static uiBlock *add_constraintmenu(void *arg_unused)
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK,"Locked Track",                0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH,"Follow Path",                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, "");
+       
+       uiDefBut(block, BUTM, B_CONSTRAINT_ADD_STRETCHTO,"Stretch To",          0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+
        if (type==TARGET_BONE) {
        
                uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
@@ -719,9 +776,8 @@ static uiBlock *add_constraintmenu(void *arg_unused)
                uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ACTION,"Action",         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, "");
-       
+
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_NULL,"Null",             0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        
        uiTextBoundsBlock(block, 50);
@@ -851,6 +907,18 @@ void do_constraintbuts(unsigned short event)
                        allqueue (REDRAWBUTSOBJECT, 0);
                }
                break;
+       case B_CONSTRAINT_ADD_STRETCHTO:
+       {
+               bConstraint *con;
+               con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
+               add_constraint_to_client(con);
+                       
+               test_scene_constraints();
+               allqueue(REDRAWVIEW3D,0);
+               allqueue(REDRAWBUTSOBJECT,0);
+       }
+               break;
+
        case B_CONSTRAINT_DEL:
                test_scene_constraints();
                allqueue (REDRAWVIEW3D, 0);
@@ -1400,7 +1468,7 @@ void object_panel_effects(Object *ob)
                        uiBlockBeginAlign(block);
                        uiDefButS(block, ROW, B_CALCEFFECT, "RGB",              911,31,45,20, &paf->texmap, 14.0, 1.0, 0, 0, "Use RGB values as a factor for particle speed");
                        uiDefButS(block, ROW, B_CALCEFFECT, "Grad",             958,31,44,20, &paf->texmap, 14.0, 2.0, 0, 0, "Use texture gradient as a factor for particle speed");
-                       uiDefButF(block, NUM, B_CALCEFFECT, "Nabla:",           911,9,91,20, &paf->nabla, 0.0001, 1.0, 1, 0, "Specify the dimension of the area for gradient calculation");
+                       uiDefButF(block, NUM, B_CALCEFFECT, "Nabla:",           911,9,91,20, &paf->nabla, 0.0001f, 1.0, 1, 0, "Specify the dimension of the area for gradient calculation");
 
                }
        }
index c06a11a6b7de308872cf2c0ee35fe2d6f5c31c37..6123da0062b638419c1ca339c0455a20fffb99ff 100644 (file)
@@ -578,6 +578,23 @@ static short detect_constraint_loop (Object *owner, const char* substring, int d
                                                }
                                        }
                                        break;
+                               case CONSTRAINT_TYPE_STRETCHTO:
+                                       {
+                                               bStretchToConstraint *data = curcon->data;
+                                       
+                                               if (!exist_object(data->tar)){
+                                                       data->tar = NULL;
+                                                       break;
+                                               }
+
+                                               if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_LOCKTRACK)){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
+                                       }
+                                       break;
                                case CONSTRAINT_TYPE_FOLLOWPATH:
                                        {
                                                bFollowPathConstraint *data = curcon->data;
@@ -827,6 +844,12 @@ char *get_con_subtarget_name(bConstraint *constraint, Object *target)
                        if (data->tar==target) return data->subtarget;
                }
                break;
+               case CONSTRAINT_TYPE_STRETCHTO:
+               {
+                       bStretchToConstraint *data = constraint->data;
+                       if (data->tar==target) return data->subtarget;
+               }
+               break;
                case CONSTRAINT_TYPE_FOLLOWPATH: 
                        /* wonder if this is relevent, since this constraint 
                         * cannot have a subtarget - theeth