2.5
authorTon Roosendaal <ton@blender.org>
Sat, 20 Dec 2008 15:42:48 +0000 (15:42 +0000)
committerTon Roosendaal <ton@blender.org>
Sat, 20 Dec 2008 15:42:48 +0000 (15:42 +0000)
- View3D: selecting added. Note it nicely respects user preset, by using
  the keymap define SELECTMOUSE.
- Added missing initialize of default vector font, so text draws.

source/blender/editors/include/ED_datafiles.h
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/space_view3d/view3d_ops.c
source/blender/windowmanager/intern/wm_event_system.c

index ddf3f0c94680106ee74a43b6046b30a88c18edf9..4ea122346af48662d28d927c406d72df7b867f50 100644 (file)
@@ -41,7 +41,7 @@ extern int datatoc_splash_jpg_size;
 extern char datatoc_splash_jpg[];
 
 extern int datatoc_Bfont_size;
-extern char datatoc_Bfont;
+extern char datatoc_Bfont[];
 
 extern int datatoc_bfont_ttf_size;
 extern char datatoc_bfont_ttf[];
index 0f9f78f6c88c58b5ac0b04d6f708be614fbc09f1..eddcdcf6d0480f0a4b97b0853d9f43c3c1484e55 100644 (file)
@@ -51,6 +51,7 @@
 
 #include "BKE_action.h"
 #include "BKE_context.h"
+#include "BKE_depsgraph.h"
 #include "BKE_object.h"
 #include "BKE_global.h"
 #include "BKE_scene.h"
@@ -893,6 +894,435 @@ void ED_VIEW3D_OT_viewcenter(wmOperatorType *ot)
        ot->poll= ED_operator_areaactive;
 }
 
+/* ************************** mouse select ************************* */
+
+
+#define MAXPICKBUF      10000
+/* The max number of menu items in an object select menu */
+#define SEL_MENU_SIZE  22
+
+void set_active_base(Scene *scene, Base *base)
+{
+       Base *tbase;
+       
+       /* activating a non-mesh, should end a couple of modes... */
+//     if(base && base->object->type!=OB_MESH)
+// XXX         exit_paint_modes();
+       
+       /* sets scene->basact */
+       BASACT= base;
+       
+       if(base) {
+               
+               /* signals to buttons */
+//             redraw_test_buttons(base->object);
+               
+               /* signal to ipo */
+//             allqueue(REDRAWIPO, base->object->ipowin);
+               
+//             allqueue(REDRAWACTION, 0);
+//             allqueue(REDRAWNLA, 0);
+//             allqueue(REDRAWNODE, 0);
+               
+               /* signal to action */
+//             select_actionchannel_by_name(base->object->action, "Object", 1);
+               
+               /* disable temporal locks */
+               for(tbase=FIRSTBASE; tbase; tbase= tbase->next) {
+                       if(base!=tbase && (tbase->object->shapeflag & OB_SHAPE_TEMPLOCK)) {
+                               tbase->object->shapeflag &= ~OB_SHAPE_TEMPLOCK;
+                               DAG_object_flush_update(G.scene, tbase->object, OB_RECALC_DATA);
+                       }
+               }
+       }
+}
+
+
+/* simple API for object selection, rather than just using the flag
+  * this takes into account the 'restrict selection in 3d view' flag.
+  * deselect works always, the restriction just prevents selection */
+void select_base_v3d(Base *base, short mode)
+{
+       if (base) {
+               if (mode==BA_SELECT) {
+                       if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
+                               if (mode==BA_SELECT) base->flag |= SELECT;
+               }
+               else if (mode==BA_DESELECT) {
+                       base->flag &= ~SELECT;
+               }
+       }
+}
+
+static void deselectall_except(Scene *scene, Base *b)   /* deselect all except b */
+{
+       Base *base;
+       
+       for(base= FIRSTBASE; base; base= base->next) {
+               if (base->flag & SELECT) {
+                       if(b!=base) {
+                               select_base_v3d(base, BA_DESELECT);
+                               base->object->flag= base->flag;
+                       }
+               }
+       }
+}
+
+static Base *mouse_select_menu(Scene *scene, ARegion *ar, View3D *v3d, unsigned int *buffer, int hits, short *mval)
+{
+       Base *baseList[SEL_MENU_SIZE]={NULL}; /*baseList is used to store all possible bases to bring up a menu */
+       Base *base;
+       short baseCount = 0;
+       char menuText[20 + SEL_MENU_SIZE*32] = "Select Object%t";       /* max ob name = 22 */
+       char str[32];
+       
+       for(base=FIRSTBASE; base; base= base->next) {
+               if (BASE_SELECTABLE(v3d, base)) {
+                       baseList[baseCount] = NULL;
+                       
+                       /* two selection methods, the CTRL select uses max dist of 15 */
+                       if(buffer) {
+                               int a;
+                               for(a=0; a<hits; a++) {
+                                       /* index was converted */
+                                       if(base->selcol==buffer[ (4 * a) + 3 ]) baseList[baseCount] = base;
+                               }
+                       }
+                       else {
+                               int temp, dist=15;
+                               
+                               project_short(ar, v3d, base->object->obmat[3], &base->sx);
+                               
+                               temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]);
+                               if(temp<dist ) baseList[baseCount] = base;
+                       }
+                       
+                       if(baseList[baseCount]) {
+                               if (baseCount < SEL_MENU_SIZE) {
+                                       baseList[baseCount] = base;
+                                       sprintf(str, "|%s %%x%d", base->object->id.name+2, baseCount+1);        /* max ob name == 22 */
+                                                       strcat(menuText, str);
+                                                       baseCount++;
+                               }
+                       }
+               }
+       }
+
+       if(baseCount<=1) return baseList[0];
+       else {
+               baseCount = -1; // XXX = pupmenu(menuText);
+               
+               if (baseCount != -1) { /* If nothing is selected then dont do anything */
+                       return baseList[baseCount-1];
+               }
+               else return NULL;
+       }
+}
+
+/* we want a select buffer with bones, if there are... */
+/* so check three selection levels and compare */
+static short mixed_bones_object_selectbuffer(Scene *scene, ARegion *ar, View3D *v3d, unsigned int *buffer, short *mval)
+{
+       rcti rect;
+       int offs;
+       short a, hits15, hits9=0, hits5=0;
+       short has_bones15=0, has_bones9=0, has_bones5=0;
+       
+       BLI_init_rcti(&rect, mval[0]-14, mval[0]+14, mval[1]-14, mval[1]+14);
+       hits15= view3d_opengl_select(scene, ar, v3d, buffer, MAXPICKBUF, &rect);
+       if(hits15>0) {
+               for(a=0; a<hits15; a++) if(buffer[4*a+3] & 0xFFFF0000) has_bones15= 1;
+               
+               offs= 4*hits15;
+               BLI_init_rcti(&rect, mval[0]-9, mval[0]+9, mval[1]-9, mval[1]+9);
+               hits9= view3d_opengl_select(scene, ar, v3d, buffer+offs, MAXPICKBUF-offs, &rect);
+               if(hits9>0) {
+                       for(a=0; a<hits9; a++) if(buffer[offs+4*a+3] & 0xFFFF0000) has_bones9= 1;
+                       
+                       offs+= 4*hits9;
+                       BLI_init_rcti(&rect, mval[0]-5, mval[0]+5, mval[1]-5, mval[1]+5);
+                       hits5= view3d_opengl_select(scene, ar, v3d, buffer+offs, MAXPICKBUF-offs, &rect);
+                       if(hits5>0) {
+                               for(a=0; a<hits5; a++) if(buffer[offs+4*a+3] & 0xFFFF0000) has_bones5= 1;
+                       }
+               }
+               
+               if(has_bones5) {
+                       offs= 4*hits15 + 4*hits9;
+                       memcpy(buffer, buffer+offs, 4*offs);
+                       return hits5;
+               }
+               if(has_bones9) {
+                       offs= 4*hits15;
+                       memcpy(buffer, buffer+offs, 4*offs);
+                       return hits9;
+               }
+               if(has_bones15) {
+                       return hits15;
+               }
+               
+               if(hits5>0) {
+                       offs= 4*hits15 + 4*hits9;
+                       memcpy(buffer, buffer+offs, 4*offs);
+                       return hits5;
+               }
+               if(hits9>0) {
+                       offs= 4*hits15;
+                       memcpy(buffer, buffer+offs, 4*offs);
+                       return hits9;
+               }
+               return hits15;
+       }
+       
+       return 0;
+}
+
+/* mval is region coords */
+static void mouse_select(Scene *scene, ARegion *ar, View3D *v3d, short *mval)
+{
+       Base *base, *startbase=NULL, *basact=NULL, *oldbasact=NULL;
+       unsigned int buffer[4*MAXPICKBUF];
+       int temp, a, dist=100;
+       short hits;
+       short ctrl=0, shift=0, alt=0;
+       
+       /* always start list from basact in wire mode */
+       startbase=  FIRSTBASE;
+       if(BASACT && BASACT->next) startbase= BASACT->next;
+       
+       /* This block uses the control key to make the object selected by its center point rather then its contents */
+       if(G.obedit==0 && ctrl) {
+               
+               /* note; shift+alt goes to group-flush-selecting */
+               if(alt && ctrl) 
+                       basact= mouse_select_menu(scene, ar, v3d, NULL, 0, mval);
+               else {
+                       base= startbase;
+                       while(base) {
+                               if (BASE_SELECTABLE(v3d, base)) {
+                                       project_short(ar, v3d, base->object->obmat[3], &base->sx);
+                                       
+                                       temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]);
+                                       if(base==BASACT) temp+=10;
+                                       if(temp<dist ) {
+                                               
+                                               dist= temp;
+                                               basact= base;
+                                       }
+                               }
+                               base= base->next;
+                               
+                               if(base==0) base= FIRSTBASE;
+                               if(base==startbase) break;
+                       }
+               }
+       }
+       else {
+               /* if objects have posemode set, the bones are in the same selection buffer */
+               
+               hits= mixed_bones_object_selectbuffer(scene, ar, v3d, buffer, mval);
+               
+               if(hits>0) {
+                       int has_bones= 0;
+                       
+                       for(a=0; a<hits; a++) if(buffer[4*a+3] & 0xFFFF0000) has_bones= 1;
+
+                       /* note; shift+alt goes to group-flush-selecting */
+                       if(has_bones==0 && (alt)) 
+                               basact= mouse_select_menu(scene, ar, v3d, buffer, hits, mval);
+                       else {
+                               static short lastmval[2]={-100, -100};
+                               int donearest= 0;
+                               
+                               /* define if we use solid nearest select or not */
+                               if(v3d->drawtype>OB_WIRE) {
+                                       donearest= 1;
+                                       if( ABS(mval[0]-lastmval[0])<3 && ABS(mval[1]-lastmval[1])<3) {
+                                               if(!has_bones)  /* hrms, if theres bones we always do nearest */
+                                                       donearest= 0;
+                                       }
+                               }
+                               lastmval[0]= mval[0]; lastmval[1]= mval[1];
+                               
+                               if(donearest) {
+                                       unsigned int min= 0xFFFFFFFF;
+                                       int selcol= 0, notcol=0;
+                                       
+
+                                       if(has_bones) {
+                                               /* we skip non-bone hits */
+                                               for(a=0; a<hits; a++) {
+                                                       if( min > buffer[4*a+1] && (buffer[4*a+3] & 0xFFFF0000) ) {
+                                                               min= buffer[4*a+1];
+                                                               selcol= buffer[4*a+3] & 0xFFFF;
+                                                       }
+                                               }
+                                       }
+                                       else {
+                                               /* only exclude active object when it is selected... */
+                                               if(BASACT && (BASACT->flag & SELECT) && hits>1) notcol= BASACT->selcol; 
+                                       
+                                               for(a=0; a<hits; a++) {
+                                                       if( min > buffer[4*a+1] && notcol!=(buffer[4*a+3] & 0xFFFF)) {
+                                                               min= buffer[4*a+1];
+                                                               selcol= buffer[4*a+3] & 0xFFFF;
+                                                       }
+                                               }
+                                       }
+
+                                       base= FIRSTBASE;
+                                       while(base) {
+                                               if(base->lay & v3d->lay) {
+                                                       if(base->selcol==selcol) break;
+                                               }
+                                               base= base->next;
+                                       }
+                                       if(base) basact= base;
+                               }
+                               else {
+                                       
+                                       base= startbase;
+                                       while(base) {
+                                               /* skip objects with select restriction, to prevent prematurely ending this loop
+                                                * with an un-selectable choice */
+                                               if (base->object->restrictflag & OB_RESTRICT_SELECT) {
+                                                       base=base->next;
+                                                       if(base==NULL) base= FIRSTBASE;
+                                                       if(base==startbase) break;
+                                               }
+                                       
+                                               if(base->lay & v3d->lay) {
+                                                       for(a=0; a<hits; a++) {
+                                                               if(has_bones) {
+                                                                       /* skip non-bone objects */
+                                                                       if((buffer[4*a+3] & 0xFFFF0000)) {
+                                                                               if(base->selcol== (buffer[(4*a)+3] & 0xFFFF))
+                                                                                       basact= base;
+                                                                       }
+                                                               }
+                                                               else {
+                                                                       if(base->selcol== (buffer[(4*a)+3] & 0xFFFF))
+                                                                               basact= base;
+                                                               }
+                                                       }
+                                               }
+                                               
+                                               if(basact) break;
+                                               
+                                               base= base->next;
+                                               if(base==NULL) base= FIRSTBASE;
+                                               if(base==startbase) break;
+                                       }
+                               }
+                       }
+                       
+                       if(has_bones && basact) {
+                               if(0) {// XXX do_pose_selectbuffer(basact, buffer, hits) ) {    /* then bone is found */
+                               
+                                       /* we make the armature selected: 
+                                          not-selected active object in posemode won't work well for tools */
+                                       basact->flag|= SELECT;
+                                       basact->object->flag= basact->flag;
+                                       
+                                       /* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */
+                                       if(G.f & G_WEIGHTPAINT) {
+                                               /* prevent activating */
+                                               basact= NULL;
+                                       }
+                               }
+                               /* prevent bone selecting to pass on to object selecting */
+                               if(basact==BASACT)
+                                       basact= NULL;
+                       }
+               }
+       }
+       
+       /* so, do we have something selected? */
+       if(basact) {
+               
+               if(G.obedit) {
+                       /* only do select */
+                       deselectall_except(scene, basact);
+                       select_base_v3d(basact, BA_SELECT);
+               }
+               /* also prevent making it active on mouse selection */
+               else if (BASE_SELECTABLE(v3d, basact)) {
+
+                       oldbasact= BASACT;
+                       BASACT= basact;
+                       
+                       if(shift==0) {
+                               deselectall_except(scene, basact);
+                               select_base_v3d(basact, BA_SELECT);
+                       }
+                       else if(shift && alt) {
+                               // XXX select_all_from_groups(basact);
+                       }
+                       else {
+                               if(basact->flag & SELECT) {
+                                       if(basact==oldbasact)
+                                               select_base_v3d(basact, BA_DESELECT);
+                               }
+                               else select_base_v3d(basact, BA_SELECT);
+                       }
+
+                       /* copy */
+                       basact->object->flag= basact->flag;
+                       
+                       if(oldbasact != basact) {
+                               set_active_base(scene, basact);
+                       }
+
+                       /* for visual speed, only in wire mode */
+                       if(v3d->drawtype==OB_WIRE) {
+                               /* however, not for posemodes */
+// XXX                         if(basact->object->flag & OB_POSEMODE);
+//                             else if(oldbasact && (oldbasact->object->flag & OB_POSEMODE));
+//                             else {
+//                                     if(oldbasact && oldbasact != basact && (oldbasact->lay & v3d->lay)) 
+//                                             draw_object_ext(oldbasact);
+//                                     draw_object_ext(basact);
+//                             }
+                       }
+                       
+               }
+       }
+
+       /* note; make it notifier! */
+       ED_region_tag_redraw(ar);
+       
+//     countall();
+
+}
+
+static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       ScrArea *sa= CTX_wm_area(C);
+       ARegion *ar= CTX_wm_region(C);
+       View3D *v3d= sa->spacedata.first;
+       short mval[2];
+       
+       /* note; otherwise opengl select won't work. do this for every glSelectBuffer() */
+       wmSubWindowSet(CTX_wm_window(C), ar->swinid);
+       
+       mval[0]= event->x - ar->winrct.xmin;
+       mval[1]= event->y - ar->winrct.ymin;
+       mouse_select(CTX_data_scene(C), ar, v3d, mval);
+
+       return OPERATOR_FINISHED;
+}
+
+void ED_VIEW3D_OT_select(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Activate/Select";
+       ot->idname= "ED_VIEW3D_OT_select";
+       
+       /* api callbacks */
+       ot->invoke= view3d_select_invoke;
+       ot->poll= ED_operator_areaactive;
+}
 
 /* ************************* below the line! *********************** */
 
index 27a07165770ad7b4013c1fd4bfecef26de8b3476..cf2a0cfe030c0f24bfd62aa8d8a4a2975f020a08 100644 (file)
@@ -67,6 +67,7 @@ void ED_VIEW3D_OT_viewmove(struct wmOperatorType *ot);
 void ED_VIEW3D_OT_viewrotate(struct wmOperatorType *ot);
 void ED_VIEW3D_OT_viewhome(struct wmOperatorType *ot);
 void ED_VIEW3D_OT_viewcenter(struct wmOperatorType *ot);
+void ED_VIEW3D_OT_select(struct wmOperatorType *ot);
 
 /* drawobject.c */
 void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag);
index 140c59eca1695861f9c77d1396c752a51a3cdb94..a8f7aa3d78953b23448de525a7a99631a7482ff3 100644 (file)
@@ -66,6 +66,7 @@ void view3d_operatortypes(void)
        WM_operatortype_append(ED_VIEW3D_OT_viewzoom);
        WM_operatortype_append(ED_VIEW3D_OT_viewhome);
        WM_operatortype_append(ED_VIEW3D_OT_viewcenter);
+       WM_operatortype_append(ED_VIEW3D_OT_select);
 }
 
 void view3d_keymap(wmWindowManager *wm)
@@ -85,6 +86,7 @@ void view3d_keymap(wmWindowManager *wm)
        RNA_boolean_set(WM_keymap_add_item(keymap, "ED_VIEW3D_OT_viewhome", HOMEKEY, KM_PRESS, 0, 0)->ptr, "center", 0);
        RNA_boolean_set(WM_keymap_add_item(keymap, "ED_VIEW3D_OT_viewhome", CKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "center", 1);
 
+       WM_keymap_add_item(keymap, "ED_VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
 
 }
 
index 086d6f3e794a62809892ca3f52b0ef1cac1a87f7..16b7e15612d7fafb136eff84ad33b912769086b1 100644 (file)
@@ -426,8 +426,18 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
 
 static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
 {
+       int kmitype= kmi->type;
        
-       if(winevent->type!=kmi->type) return 0;
+       /* first do default mappings */
+       if(kmitype==SELECTMOUSE) {
+               if(U.flag & USER_LMOUSESELECT)
+                       kmitype= LEFTMOUSE;
+               else
+                       kmitype= RIGHTMOUSE;
+       }
+       
+       /* the matching rules */
+       if(winevent->type!=kmitype) return 0;
        
        if(kmi->val!=KM_ANY)
                if(winevent->val!=kmi->val) return 0;