Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_view3d/view3d_select.c
| Show First 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | |||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_sculpt.h" | #include "ED_sculpt.h" | ||||
| #include "ED_mball.h" | #include "ED_mball.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "GPU_draw.h" | #include "GPU_draw.h" | ||||
| #include "GPU_select.h" | |||||
| #include "view3d_intern.h" /* own include */ | #include "view3d_intern.h" /* own include */ | ||||
| float ED_view3d_select_dist_px(void) | float ED_view3d_select_dist_px(void) | ||||
| { | { | ||||
| return 75.0f * U.pixelsize; | return 75.0f * U.pixelsize; | ||||
| } | } | ||||
| /* TODO: should return whether there is valid context to continue */ | /* TODO: should return whether there is valid context to continue */ | ||||
| ▲ Show 20 Lines • Show All 1,066 Lines • ▼ Show 20 Lines | for (i = 0; i < hits; i++) { | ||||
| if (buffer[(4 * i) + 3] & 0xFFFF0000) { | if (buffer[(4 * i) + 3] & 0xFFFF0000) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* utility function for mixed_bones_object_selectbuffer */ | /* utility function for mixed_bones_object_selectbuffer */ | ||||
| static short selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const short hits15) | static int selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const int hits15) | ||||
| { | { | ||||
| return hits15; | return hits15; | ||||
| } | } | ||||
| static short selectbuffer_ret_hits_9(unsigned int *buffer, const short hits15, const short hits9) | static int selectbuffer_ret_hits_9(unsigned int *buffer, const int hits15, const int hits9) | ||||
| { | { | ||||
| const int offs = 4 * hits15; | const int offs = 4 * hits15; | ||||
| memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(unsigned int)); | memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(unsigned int)); | ||||
| return hits9; | return hits9; | ||||
| } | } | ||||
| static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, const short hits9, const short hits5) | static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const int hits9, const int hits5) | ||||
| { | { | ||||
| const int offs = 4 * hits15 + 4 * hits9; | const int offs = 4 * hits15 + 4 * hits9; | ||||
| memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int)); | memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int)); | ||||
| return hits5; | return hits5; | ||||
| } | } | ||||
| /* we want a select buffer with bones, if there are... */ | /* we want a select buffer with bones, if there are... */ | ||||
| /* so check three selection levels and compare */ | /* so check three selection levels and compare */ | ||||
| static short mixed_bones_object_selectbuffer( | static int mixed_bones_object_selectbuffer( | ||||
| ViewContext *vc, unsigned int *buffer, const int mval[2], | ViewContext *vc, unsigned int *buffer, const int mval[2], | ||||
| bool use_cycle, bool enumerate, | bool use_cycle, bool enumerate, | ||||
| bool *r_do_nearest) | bool *r_do_nearest) | ||||
| { | { | ||||
| rcti rect; | rcti rect; | ||||
| int offs; | int offs; | ||||
| short hits15, hits9 = 0, hits5 = 0; | int hits15, hits9 = 0, hits5 = 0; | ||||
| bool has_bones15 = false, has_bones9 = false, has_bones5 = false; | bool has_bones15 = false, has_bones9 = false, has_bones5 = false; | ||||
| static int last_mval[2] = {-100, -100}; | static int last_mval[2] = {-100, -100}; | ||||
| bool do_nearest = false; | bool do_nearest = false; | ||||
| View3D *v3d = vc->v3d; | View3D *v3d = vc->v3d; | ||||
| /* define if we use solid nearest select or not */ | /* define if we use solid nearest select or not */ | ||||
| if (use_cycle) { | if (use_cycle) { | ||||
| if (v3d->drawtype > OB_WIRE) { | if (v3d->drawtype > OB_WIRE) { | ||||
| Show All 11 Lines | static int mixed_bones_object_selectbuffer( | ||||
| } | } | ||||
| if (r_do_nearest) { | if (r_do_nearest) { | ||||
| *r_do_nearest = do_nearest; | *r_do_nearest = do_nearest; | ||||
| } | } | ||||
| do_nearest = do_nearest && !enumerate; | do_nearest = do_nearest && !enumerate; | ||||
| BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14); | const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_SORT_NEAREST : VIEW3D_SELECT_PICK_SORT_ALL); | ||||
| hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, do_nearest); | int hits = 0; | ||||
| /* we _must_ end cache before return, use 'goto finally' */ | |||||
| GPU_select_cache_begin(); | |||||
| BLI_rcti_init_pt_size(&rect, mval, 14); | |||||
| hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); | |||||
| if (hits15 == 1) { | if (hits15 == 1) { | ||||
| return selectbuffer_ret_hits_15(buffer, hits15); | hits = selectbuffer_ret_hits_15(buffer, hits15); | ||||
| goto finally; | |||||
| } | } | ||||
| else if (hits15 > 0) { | else if (hits15 > 0) { | ||||
| has_bones15 = selectbuffer_has_bones(buffer, hits15); | has_bones15 = selectbuffer_has_bones(buffer, hits15); | ||||
| offs = 4 * hits15; | offs = 4 * hits15; | ||||
| BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9); | BLI_rcti_init_pt_size(&rect, mval, 9); | ||||
| hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest); | hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); | ||||
| if (hits9 == 1) { | if (hits9 == 1) { | ||||
| return selectbuffer_ret_hits_9(buffer, hits15, hits9); | hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); | ||||
| goto finally; | |||||
| } | } | ||||
| else if (hits9 > 0) { | else if (hits9 > 0) { | ||||
| has_bones9 = selectbuffer_has_bones(buffer + offs, hits9); | has_bones9 = selectbuffer_has_bones(buffer + offs, hits9); | ||||
| offs += 4 * hits9; | offs += 4 * hits9; | ||||
| BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5); | BLI_rcti_init_pt_size(&rect, mval, 5); | ||||
| hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest); | hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); | ||||
| if (hits5 == 1) { | if (hits5 == 1) { | ||||
| return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); | hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); | ||||
| goto finally; | |||||
| } | } | ||||
| else if (hits5 > 0) { | else if (hits5 > 0) { | ||||
| has_bones5 = selectbuffer_has_bones(buffer + offs, hits5); | has_bones5 = selectbuffer_has_bones(buffer + offs, hits5); | ||||
| } | } | ||||
| } | } | ||||
| if (has_bones5) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); | if (has_bones5) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; } | ||||
| else if (has_bones9) return selectbuffer_ret_hits_9(buffer, hits15, hits9); | else if (has_bones9) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; } | ||||
| else if (has_bones15) return selectbuffer_ret_hits_15(buffer, hits15); | else if (has_bones15) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; } | ||||
| if (hits5 > 0) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); | if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; } | ||||
| else if (hits9 > 0) return selectbuffer_ret_hits_9(buffer, hits15, hits9); | else if (hits9 > 0) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; } | ||||
| else return selectbuffer_ret_hits_15(buffer, hits15); | else { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; } | ||||
| } | } | ||||
| return 0; | finally: | ||||
| GPU_select_cache_end(); | |||||
| return hits; | |||||
| } | } | ||||
| /* returns basact */ | /* returns basact */ | ||||
| static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, | static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, | ||||
| Base *startbase, bool has_bones, bool do_nearest) | Base *startbase, bool has_bones, bool do_nearest) | ||||
| { | { | ||||
| Scene *scene = vc->scene; | Scene *scene = vc->scene; | ||||
| View3D *v3d = vc->v3d; | View3D *v3d = vc->v3d; | ||||
| ▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | static bool ed_object_select_pick( | ||||
| ViewContext vc; | ViewContext vc; | ||||
| ARegion *ar = CTX_wm_region(C); | ARegion *ar = CTX_wm_region(C); | ||||
| View3D *v3d = CTX_wm_view3d(C); | View3D *v3d = CTX_wm_view3d(C); | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL; | Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL; | ||||
| bool is_obedit; | bool is_obedit; | ||||
| float dist = ED_view3d_select_dist_px() * 1.3333f; | float dist = ED_view3d_select_dist_px() * 1.3333f; | ||||
| bool retval = false; | bool retval = false; | ||||
| short hits; | int hits; | ||||
| const float mval_fl[2] = {(float)mval[0], (float)mval[1]}; | const float mval_fl[2] = {(float)mval[0], (float)mval[1]}; | ||||
| /* setup view context for argument to callbacks */ | /* setup view context for argument to callbacks */ | ||||
| view3d_set_viewcontext(C, &vc); | view3d_set_viewcontext(C, &vc); | ||||
| is_obedit = (vc.obedit != NULL); | is_obedit = (vc.obedit != NULL); | ||||
| if (object) { | if (object) { | ||||
| ▲ Show 20 Lines • Show All 475 Lines • ▼ Show 20 Lines | |||||
| static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) | static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) | ||||
| { | { | ||||
| MetaBall *mb = (MetaBall *)vc->obedit->data; | MetaBall *mb = (MetaBall *)vc->obedit->data; | ||||
| MetaElem *ml; | MetaElem *ml; | ||||
| int a; | int a; | ||||
| unsigned int buffer[MAXPICKBUF]; | unsigned int buffer[MAXPICKBUF]; | ||||
| short hits; | int hits; | ||||
| hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false); | hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); | ||||
| if (extend == false && select) | if (extend == false && select) | ||||
| BKE_mball_deselect_all(mb); | BKE_mball_deselect_all(mb); | ||||
| for (ml = mb->editelems->first; ml; ml = ml->next) { | for (ml = mb->editelems->first; ml; ml = ml->next) { | ||||
| for (a = 0; a < hits; a++) { | for (a = 0; a < hits; a++) { | ||||
| if (ml->selcol1 == buffer[(4 * a) + 3]) { | if (ml->selcol1 == buffer[(4 * a) + 3]) { | ||||
| ml->flag |= MB_SCALE_RAD; | ml->flag |= MB_SCALE_RAD; | ||||
| Show All 15 Lines | |||||
| static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) | static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) | ||||
| { | { | ||||
| bArmature *arm = vc->obedit->data; | bArmature *arm = vc->obedit->data; | ||||
| EditBone *ebone; | EditBone *ebone; | ||||
| int a; | int a; | ||||
| unsigned int buffer[MAXPICKBUF]; | unsigned int buffer[MAXPICKBUF]; | ||||
| short hits; | int hits; | ||||
| hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false); | hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); | ||||
| /* clear flag we use to detect point was affected */ | /* clear flag we use to detect point was affected */ | ||||
| for (ebone = arm->edbo->first; ebone; ebone = ebone->next) | for (ebone = arm->edbo->first; ebone; ebone = ebone->next) | ||||
| ebone->flag &= ~BONE_DONE; | ebone->flag &= ~BONE_DONE; | ||||
| if (extend == false && select) | if (extend == false && select) | ||||
| ED_armature_deselect_all_visible(vc->obedit); | ED_armature_deselect_all_visible(vc->obedit); | ||||
| ▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| Bone *bone; | Bone *bone; | ||||
| Object *ob = vc->obact; | Object *ob = vc->obact; | ||||
| unsigned int *vbuffer = NULL; /* selection buffer */ | unsigned int *vbuffer = NULL; /* selection buffer */ | ||||
| unsigned int *col; /* color in buffer */ | unsigned int *col; /* color in buffer */ | ||||
| int bone_only; | int bone_only; | ||||
| int bone_selected = 0; | int bone_selected = 0; | ||||
| int totobj = MAXPICKBUF; /* XXX solve later */ | int totobj = MAXPICKBUF; /* XXX solve later */ | ||||
| short hits; | int hits; | ||||
| if ((ob) && (ob->mode & OB_MODE_POSE)) | if ((ob) && (ob->mode & OB_MODE_POSE)) | ||||
| bone_only = 1; | bone_only = 1; | ||||
| else | else | ||||
| bone_only = 0; | bone_only = 0; | ||||
| if (extend == false && select) { | if (extend == false && select) { | ||||
| if (bone_only) { | if (bone_only) { | ||||
| CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) | CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) | ||||
| { | { | ||||
| if ((select == false) || ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)) { | if ((select == false) || ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)) { | ||||
| pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); | pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); | ||||
| } | } | ||||
| } | } | ||||
| CTX_DATA_END; | CTX_DATA_END; | ||||
| } | } | ||||
| else { | else { | ||||
| object_deselect_all_visible(vc->scene, vc->v3d); | object_deselect_all_visible(vc->scene, vc->v3d); | ||||
| } | } | ||||
| } | } | ||||
| /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ | /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ | ||||
| vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer"); | vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer"); | ||||
| hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, false); | hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL); | ||||
| /* | /* | ||||
| * LOGIC NOTES (theeth): | * LOGIC NOTES (theeth): | ||||
| * The buffer and ListBase have the same relative order, which makes the selection | * The buffer and ListBase have the same relative order, which makes the selection | ||||
| * very simple. Loop through both data sets at the same time, if the color | * very simple. Loop through both data sets at the same time, if the color | ||||
| * is the same as the object, we have a hit and can move to the next color | * is the same as the object, we have a hit and can move to the next color | ||||
| * and object pair, if not, just move to the next object, | * and object pair, if not, just move to the next object, | ||||
| * keeping the same color until we have a hit. | * keeping the same color until we have a hit. | ||||
| * | * | ||||
| ▲ Show 20 Lines • Show All 837 Lines • Show Last 20 Lines | |||||