Sculpt:
[blender.git] / source / blender / editors / space_view3d / view3d_select.c
index 0c90347..f0ebb21 100644 (file)
@@ -49,7 +49,7 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_editVert.h"
 #include "BLI_rand.h"
@@ -120,28 +120,28 @@ void view3d_get_view_aligned_coordinate(ViewContext *vc, float *fp, short mval[2
        
        if(mval[0]!=IS_CLIPPED) {
                window_to_3d_delta(vc->ar, dvec, mval[0]-mx, mval[1]-my);
-               VecSubf(fp, fp, dvec);
+               sub_v3_v3v3(fp, fp, dvec);
        }
 }
 
-void view3d_get_transformation(ViewContext *vc, Object *ob, bglMats *mats)
+void view3d_get_transformation(ARegion *ar, RegionView3D *rv3d, Object *ob, bglMats *mats)
 {
        float cpy[4][4];
        int i, j;
 
-       Mat4MulMat4(cpy, ob->obmat, vc->rv3d->viewmat);
+       mul_m4_m4m4(cpy, ob->obmat, rv3d->viewmat);
 
        for(i = 0; i < 4; ++i) {
                for(j = 0; j < 4; ++j) {
-                       mats->projection[i*4+j] = vc->rv3d->winmat[i][j];
+                       mats->projection[i*4+j] = rv3d->winmat[i][j];
                        mats->modelview[i*4+j] = cpy[i][j];
                }
        }
 
-       mats->viewport[0] = vc->ar->winrct.xmin;
-       mats->viewport[1] = vc->ar->winrct.ymin;
-       mats->viewport[2] = vc->ar->winx;
-       mats->viewport[3] = vc->ar->winy;       
+       mats->viewport[0] = ar->winrct.xmin;
+       mats->viewport[1] = ar->winrct.ymin;
+       mats->viewport[2] = ar->winx;
+       mats->viewport[3] = ar->winy;   
 }
 
 /* ********************** view3d_select: selection manipulations ********************* */
@@ -326,9 +326,9 @@ int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, in
        
        /* no points in lasso, so we have to intersect with lasso edge */
        
-       if( IsectLL2Ds(mcords[0], mcords[moves-1], v1, v2) > 0) return 1;
+       if( isect_line_line_v2_short(mcords[0], mcords[moves-1], v1, v2) > 0) return 1;
        for(a=0; a<moves-1; a++) {
-               if( IsectLL2Ds(mcords[a], mcords[a+1], v1, v2) > 0) return 1;
+               if( isect_line_line_v2_short(mcords[a], mcords[a+1], v1, v2) > 0) return 1;
        }
        
        return 0;
@@ -349,15 +349,22 @@ static void do_lasso_select_pose(ViewContext *vc, short mcords[][2], short moves
        
        for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
                VECCOPY(vec, pchan->pose_head);
-               Mat4MulVecfl(ob->obmat, vec);
+               mul_m4_v3(ob->obmat, vec);
                project_short(vc->ar, vec, sco1);
                VECCOPY(vec, pchan->pose_tail);
-               Mat4MulVecfl(ob->obmat, vec);
+               mul_m4_v3(ob->obmat, vec);
                project_short(vc->ar, vec, sco2);
                
                if(lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) {
                        if(select) pchan->bone->flag |= BONE_SELECTED;
-                       else pchan->bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED);
+                       else pchan->bone->flag &= ~BONE_SELECTED;
+               }
+       }
+       
+       {
+               bArmature *arm= ob->data;
+               if(arm->act_bone && (arm->act_bone->flag & BONE_SELECTED)==0) {
+                       arm->act_bone= NULL;
                }
        }
 }
@@ -618,10 +625,10 @@ static void do_lasso_select_armature(ViewContext *vc, short mcords[][2], short m
        for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
 
                VECCOPY(vec, ebone->head);
-               Mat4MulVecfl(vc->obedit->obmat, vec);
+               mul_m4_v3(vc->obedit->obmat, vec);
                project_short(vc->ar, vec, sco1);
                VECCOPY(vec, ebone->tail);
-               Mat4MulVecfl(vc->obedit->obmat, vec);
+               mul_m4_v3(vc->obedit->obmat, vec);
                project_short(vc->ar, vec, sco2);
                
                didpoint= 0;
@@ -638,9 +645,11 @@ static void do_lasso_select_armature(ViewContext *vc, short mcords[][2], short m
                /* if one of points selected, we skip the bone itself */
                if(didpoint==0 && lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) {
                        if(select) ebone->flag |= BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED;
-                       else ebone->flag &= ~(BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                       else ebone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                }
        }
+
+       ED_armature_validate_active(arm);
 }
 
 static void do_lasso_select_facemode(ViewContext *vc, short mcords[][2], short moves, short select)
@@ -990,7 +999,7 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
 
 
 /* mval is region coords */
-static void mouse_select(bContext *C, short *mval, short extend, short obcenter, short enumerate)
+static int mouse_select(bContext *C, short *mval, short extend, short obcenter, short enumerate)
 {
        ViewContext vc;
        ARegion *ar= CTX_wm_region(C);
@@ -998,6 +1007,7 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter,
        Scene *scene= CTX_data_scene(C);
        Base *base, *startbase=NULL, *basact=NULL, *oldbasact=NULL;
        int temp, a, dist=100;
+       int retval = 0;
        short hits;
        
        /* setup view context for argument to callbacks */
@@ -1144,6 +1154,7 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter,
                                        basact->flag|= SELECT;
                                        basact->object->flag= basact->flag;
                                        
+                                       retval = 1;
                                        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, basact->object);
                                        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, basact->object);
                                        
@@ -1163,6 +1174,7 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter,
        
        /* so, do we have something selected? */
        if(basact) {
+               retval = 1;
                
                if(vc.obedit) {
                        /* only do select */
@@ -1196,6 +1208,8 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter,
                        WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
                }
        }
+
+       return retval;
 }
 
 /* ********************  border and circle ************************************** */
@@ -1218,7 +1232,7 @@ int edge_inside_circle(short centx, short centy, short rad, short x1, short y1,
        v2[0]= x2;
        v2[1]= y2;
        
-       if( PdistVL2Dfl(v3, v1, v2) < (float)rad ) return 1;
+       if( dist_to_line_segment_v2(v3, v1, v2) < (float)rad ) return 1;
        
        return 0;
 }
@@ -1373,38 +1387,38 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
        MetaElem *ml;
        unsigned int buffer[4*MAXPICKBUF];
        int a, index;
-       short hits, val;
+       short hits, selecting;
 
        view3d_operator_needs_opengl(C);
        
        /* setup view context for argument to callbacks */
        view3d_set_viewcontext(C, &vc);
        
-       val= RNA_int_get(op->ptr, "event_type");
+       selecting= (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT);
        rect.xmin= RNA_int_get(op->ptr, "xmin");
        rect.ymin= RNA_int_get(op->ptr, "ymin");
        rect.xmax= RNA_int_get(op->ptr, "xmax");
        rect.ymax= RNA_int_get(op->ptr, "ymax");
        
        if(obedit==NULL && (paint_facesel_test(OBACT))) {
-               face_borderselect(C, obact, &rect, (val==LEFTMOUSE));
+               face_borderselect(C, obact, &rect, selecting);
                return OPERATOR_FINISHED;
        }
        else if(obedit==NULL && (obact && obact->mode & OB_MODE_PARTICLE_EDIT)) {
-               return PE_border_select(C, &rect, (val==LEFTMOUSE));
+               return PE_border_select(C, &rect, selecting);
        }
        
        if(obedit) {
                if(obedit->type==OB_MESH) {
                        Mesh *me= obedit->data;
                        vc.em= me->edit_mesh;
-                       do_mesh_box_select(&vc, &rect, (val==LEFTMOUSE));
+                       do_mesh_box_select(&vc, &rect, selecting);
 //                     if (EM_texFaceCheck())
                        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
                        
                }
                else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
-                       do_nurbs_box_select(&vc, &rect, val==LEFTMOUSE);
+                       do_nurbs_box_select(&vc, &rect, selecting);
                }
                else if(obedit->type==OB_MBALL) {
                        MetaBall *mb = (MetaBall*)obedit->data;
@@ -1416,14 +1430,14 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
                                for(a=0; a<hits; a++) {
                                        if(ml->selcol1==buffer[ (4 * a) + 3 ]) {
                                                ml->flag |= MB_SCALE_RAD;
-                                               if(val==LEFTMOUSE) ml->flag |= SELECT;
-                                               else ml->flag &= ~SELECT;
+                                               if(selecting)   ml->flag |= SELECT;
+                                               else                    ml->flag &= ~SELECT;
                                                break;
                                        }
                                        if(ml->selcol2==buffer[ (4 * a) + 3 ]) {
                                                ml->flag &= ~MB_SCALE_RAD;
-                                               if(val==LEFTMOUSE) ml->flag |= SELECT;
-                                               else ml->flag &= ~SELECT;
+                                               if(selecting)   ml->flag |= SELECT;
+                                               else                    ml->flag &= ~SELECT;
                                                break;
                                        }
                                }
@@ -1447,14 +1461,14 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
                                        ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
                                        if (index & BONESEL_TIP) {
                                                ebone->flag |= BONE_DONE;
-                                               if (val==LEFTMOUSE) ebone->flag |= BONE_TIPSEL;
-                                               else ebone->flag &= ~BONE_TIPSEL;
+                                               if (selecting)  ebone->flag |= BONE_TIPSEL;
+                                               else                    ebone->flag &= ~BONE_TIPSEL;
                                        }
                                        
                                        if (index & BONESEL_ROOT) {
                                                ebone->flag |= BONE_DONE;
-                                               if (val==LEFTMOUSE) ebone->flag |= BONE_ROOTSEL;
-                                               else ebone->flag &= ~BONE_ROOTSEL;
+                                               if (selecting)  ebone->flag |= BONE_ROOTSEL;
+                                               else                    ebone->flag &= ~BONE_ROOTSEL;
                                        }
                                }
                        }
@@ -1474,7 +1488,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
                                        ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
                                        if (index & BONESEL_BONE) {
                                                if(!(ebone->flag & BONE_DONE)) {
-                                                       if (val==LEFTMOUSE)
+                                                       if (selecting)
                                                                ebone->flag |= (BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
                                                        else
                                                                ebone->flag &= ~(BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
@@ -1486,7 +1500,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
                        ED_armature_sync_selection(arm->edbo);
                }
                else if(obedit->type==OB_LATTICE) {
-                       do_lattice_box_select(&vc, &rect, val==LEFTMOUSE);
+                       do_lattice_box_select(&vc, &rect, selecting);
                }
        }
        else {  /* no editmode, unified for bones and objects */
@@ -1494,7 +1508,6 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
                Object *ob= OBACT;
                unsigned int *vbuffer=NULL; /* selection buffer */
                unsigned int *col;                      /* color in buffer      */
-               short selecting = 0;
                int bone_only;
                int totobj= MAXPICKBUF; // XXX solve later
                
@@ -1503,9 +1516,6 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
                else
                        bone_only= 0;
                
-               if (val==LEFTMOUSE)
-                       selecting = 1;
-               
                /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
                vbuffer = MEM_mallocN(4 * (totobj+MAXPICKBUF) * sizeof(unsigned int), "selection buffer");
                hits= view3d_opengl_select(&vc, vbuffer, 4*(totobj+MAXPICKBUF), &rect);
@@ -1538,8 +1548,12 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
 // XXX                                                                 select_actionchannel_by_name(base->object->action, bone->name, 1);
                                                                }
                                                                else {
-                                                                       bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED);
+                                                                       bArmature *arm= base->object->data;
+                                                                       bone->flag &= ~BONE_SELECTED;
 // XXX                                                                 select_actionchannel_by_name(base->object->action, bone->name, 0);
+                                                                       if(arm->act_bone==bone)
+                                                                               arm->act_bone= NULL;
+                                                                       
                                                                }
                                                        }
                                                }
@@ -1589,13 +1603,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
        ot->flag= OPTYPE_UNDO;
        
        /* rna */
-       RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
-       RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
-       RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
-       RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
-       RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
-
-       RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first.");
+       WM_operator_properties_gesture_border(ot, TRUE);
 }
 
 /* ****** Mouse Select ****** */
@@ -1608,31 +1616,37 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
        short extend= RNA_boolean_get(op->ptr, "extend");
        short center= RNA_boolean_get(op->ptr, "center");
        short enumerate= RNA_boolean_get(op->ptr, "enumerate");
+       int     retval = 0;
 
        view3d_operator_needs_opengl(C);
        
        if(obedit) {
                if(obedit->type==OB_MESH)
-                       mouse_mesh(C, event->mval, extend);
+                       retval = mouse_mesh(C, event->mval, extend);
                else if(obedit->type==OB_ARMATURE)
-                       mouse_armature(C, event->mval, extend);
+                       retval = mouse_armature(C, event->mval, extend);
                else if(obedit->type==OB_LATTICE)
-                       mouse_lattice(C, event->mval, extend);
+                       retval = mouse_lattice(C, event->mval, extend);
                else if(ELEM(obedit->type, OB_CURVE, OB_SURF))
-                       mouse_nurb(C, event->mval, extend);
+                       retval = mouse_nurb(C, event->mval, extend);
                else if(obedit->type==OB_MBALL)
-                       mouse_mball(C, event->mval, extend);
+                       retval = mouse_mball(C, event->mval, extend);
                        
        }
        else if(obact && obact->mode & OB_MODE_PARTICLE_EDIT)
-               PE_mouse_particles(C, event->mval, extend);
+               return PE_mouse_particles(C, event->mval, extend);
        else if(obact && paint_facesel_test(obact))
-               face_select(C, obact, event->mval, extend);
+               retval = face_select(C, obact, event->mval, extend);
        else
-               mouse_select(C, event->mval, extend, center, enumerate);
+               retval = mouse_select(C, event->mval, extend, center, enumerate);
 
-       /* allowing tweaks */
-       return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
+       /* passthrough allows tweaks
+        * FINISHED to signal one operator worked
+        * */
+       if (retval)
+               return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
+       else
+               return OPERATOR_PASS_THROUGH; /* nothing selected, just passthrough */
 }
 
 void VIEW3D_OT_select(wmOperatorType *ot)
@@ -1714,6 +1728,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
 
                vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
 
+               data.vc = vc;
                data.select = selecting;
                data.mval[0] = mval[0];
                data.mval[1] = mval[1];
@@ -1856,12 +1871,12 @@ static void armature_circle_select(ViewContext *vc, int selecting, short *mval,
                
                /* project head location to screenspace */
                VECCOPY(vec, ebone->head);
-               Mat4MulVecfl(vc->obedit->obmat, vec);
+               mul_m4_v3(vc->obedit->obmat, vec);
                project_short(vc->ar, vec, sco1);
                
                /* project tail location to screenspace */
                VECCOPY(vec, ebone->tail);
-               Mat4MulVecfl(vc->obedit->obmat, vec);
+               mul_m4_v3(vc->obedit->obmat, vec);
                project_short(vc->ar, vec, sco2);
                
                /* check if the head and/or tail is in the circle 
@@ -1878,9 +1893,11 @@ static void armature_circle_select(ViewContext *vc, int selecting, short *mval,
                        if (selecting) 
                                ebone->flag |= BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED;
                        else 
-                               ebone->flag &= ~(BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); 
+                               ebone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                }
        }
+
+       ED_armature_validate_active(arm);
 }
 
 /** Callbacks for circle selection in Editmode */
@@ -1917,17 +1934,20 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
        int x= RNA_int_get(op->ptr, "x");
        int y= RNA_int_get(op->ptr, "y");
        int radius= RNA_int_get(op->ptr, "radius");
+    int gesture_mode= RNA_int_get(op->ptr, "gesture_mode");
+    int selecting;
        
+    selecting= (gesture_mode==GESTURE_MODAL_SELECT);
+    
        if(CTX_data_edit_object(C) || (obact && obact->mode & OB_MODE_PARTICLE_EDIT)) {
                ViewContext vc;
-               short mval[2], selecting;
+               short mval[2];
                
                view3d_operator_needs_opengl(C);
                
                view3d_set_viewcontext(C, &vc);
                mval[0]= x;
                mval[1]= y;
-               selecting= LEFTMOUSE==RNA_int_get(op->ptr, "event_type"); // XXX solve
 
                if(CTX_data_edit_object(C)) {
                        obedit_circle_select(&vc, selecting, mval, (float)radius);
@@ -1938,7 +1958,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
        }
        else {
                Base *base;
-               
+               selecting= selecting?BA_SELECT:BA_DESELECT;
                for(base= FIRSTBASE; base; base= base->next) {
                        if(base->lay & v3d->lay) {
                                project_short(ar, base->object->obmat[3], &base->sx);
@@ -1946,7 +1966,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
                                        int dx= base->sx-x;
                                        int dy= base->sy-y;
                                        if( dx*dx + dy*dy < radius*radius)
-                                               ED_base_object_select(base, BA_SELECT);
+                                               ED_base_object_select(base, selecting);
                                }
                        }
                }
@@ -1974,5 +1994,5 @@ void VIEW3D_OT_select_circle(wmOperatorType *ot)
        RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX);
-       RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
 }