Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_select.c')
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c588
1 files changed, 346 insertions, 242 deletions
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index e409ad4e81e..8510e39271b 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -110,15 +110,16 @@ int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int m
{
float dvec[3];
int mval_cpy[2];
+ eV3DProjStatus ret;
mval_cpy[0] = mval[0];
mval_cpy[1] = mval[1];
- ED_view3d_project_int_noclip(vc->ar, fp, mval_cpy);
+ ret = ED_view3d_project_int_global(vc->ar, fp, mval_cpy, V3D_PROJ_TEST_NOP);
initgrabz(vc->rv3d, fp[0], fp[1], fp[2]);
- if (mval_cpy[0] != IS_CLIPPED) {
+ if (ret == V3D_PROJ_RET_SUCCESS) {
const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]),
(float)(mval_cpy[1] - mval[1])};
ED_view3d_win_to_delta(vc->ar, mval_f, dvec);
@@ -255,10 +256,33 @@ static void edbm_backbuf_check_and_select_tfaces(Mesh *me, int select)
typedef struct LassoSelectUserData {
ViewContext *vc;
- rcti *rect;
- int (*mcords)[2], moves, select, pass, done;
+ const rcti *rect;
+ const int (*mcords)[2];
+ int moves;
+ int select;
+
+ /* runtime */
+ int pass;
+ int is_done;
+ int is_change;
} LassoSelectUserData;
+static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
+ ViewContext *vc, const rcti *rect, const int (*mcords)[2],
+ const int moves, const int select)
+{
+ r_data->vc = vc;
+ r_data->rect = rect;
+ r_data->mcords = mcords;
+ r_data->moves = moves;
+ r_data->select = select;
+
+ /* runtime */
+ r_data->pass = 0;
+ r_data->is_done = FALSE;
+ r_data->is_change = FALSE;
+}
+
static int view3d_selectable_data(bContext *C)
{
Object *ob = CTX_data_active_object(C);
@@ -289,12 +313,12 @@ static int view3d_selectable_data(bContext *C)
/* helper also for borderselect */
-static int edge_fully_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
+static int edge_fully_inside_rect(const rcti *rect, int x1, int y1, int x2, int y2)
{
return BLI_rcti_isect_pt(rect, x1, y1) && BLI_rcti_isect_pt(rect, x2, y2);
}
-static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
+static int edge_inside_rect(const rcti *rect, int x1, int y1, int x2, int y2)
{
int d1, d2, d3, d4;
@@ -319,35 +343,70 @@ static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
return 1;
}
-/* warning; lasso select with backbuffer-check draws in backbuf with persp(PERSP_WIN)
- * and returns with persp(PERSP_VIEW). After lasso select backbuf is not OK
- */
-static void do_lasso_select_pose(ViewContext *vc, Object *ob, int mcords[][2], short moves, short select)
+static void do_lasso_select_pose__doSelectBone(void *userData, struct bPoseChannel *pchan, int x0, int y0, int x1, int y1)
{
- bPoseChannel *pchan;
- float vec[3];
- int sco1[2], sco2[2];
- bArmature *arm = ob->data;
-
- if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) return;
+ LassoSelectUserData *data = userData;
+ bArmature *arm = data->vc->obact->data;
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (PBONE_VISIBLE(arm, pchan->bone) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- mul_v3_m4v3(vec, ob->obmat, pchan->pose_head);
- ED_view3d_project_int(vc->ar, vec, sco1);
- mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
- ED_view3d_project_int(vc->ar, vec, sco2);
-
- if (BLI_lasso_is_edge_inside(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1], IS_CLIPPED)) {
- if (select) pchan->bone->flag |= BONE_SELECTED;
- else pchan->bone->flag &= ~BONE_SELECTED;
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ int is_point_done = FALSE;
+ int points_proj_tot = 0;
+
+ /* project head location to screenspace */
+ if (x0 != IS_CLIPPED) {
+ points_proj_tot++;
+ if (BLI_rcti_isect_pt(data->rect, x0, y0) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX))
+ {
+ is_point_done = TRUE;
+ }
+ }
+
+ /* project tail location to screenspace */
+ if (x1 != IS_CLIPPED) {
+ points_proj_tot++;
+ if (BLI_rcti_isect_pt(data->rect, x1, y1) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX))
+ {
+ is_point_done = TRUE;
}
}
+
+ /* if one of points selected, we skip the bone itself */
+ if ((is_point_done == TRUE) ||
+ ((is_point_done == FALSE) && (points_proj_tot == 2) &&
+ BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX)))
+ {
+ if (data->select) pchan->bone->flag |= BONE_SELECTED;
+ else pchan->bone->flag &= ~BONE_SELECTED;
+ data->is_change = TRUE;
+ }
+ data->is_change |= is_point_done;
}
+}
+static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves, short select)
+{
+ LassoSelectUserData data;
+ rcti rect;
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) {
+ return;
+ }
+
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ pose_foreachScreenBone(vc, do_lasso_select_pose__doSelectBone, &data);
+
+ if (data.is_change) {
+ bArmature *arm = ob->data;
+ if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* mask modifier ('armature' mode), etc. */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
}
}
@@ -362,7 +421,7 @@ static void object_deselect_all_visible(Scene *scene, View3D *v3d)
}
}
-static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], const short moves, short extend, short select)
{
Base *base;
@@ -371,7 +430,7 @@ static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short move
for (base = vc->scene->base.first; base; base = base->next) {
if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */
- ED_view3d_project_short(vc->ar, base->object->obmat[3], &base->sx);
+ ED_view3d_project_base(vc->ar, base);
if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
if (select) ED_base_object_select(base, BA_SELECT);
@@ -406,7 +465,7 @@ static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int
BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, IS_CLIPPED))
{
BM_edge_select_set(data->vc->em->bm, eed, data->select);
- data->done = TRUE;
+ data->is_done = TRUE;
}
}
else {
@@ -427,7 +486,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, int
}
}
-static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
{
LassoSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
@@ -439,13 +498,7 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
/* set editmesh */
vc->em = BMEdit_FromObject(vc->obedit);
- data.vc = vc;
- data.rect = ▭
- data.mcords = mcords;
- data.moves = moves;
- data.select = select;
- data.done = FALSE;
- data.pass = 0;
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
if (extend == 0 && select)
EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
@@ -469,7 +522,7 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
data.pass = 0;
mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_CLIP_TEST_OFF);
- if (data.done == 0) {
+ if (data.is_done == 0) {
data.pass = 1;
mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_CLIP_TEST_OFF);
}
@@ -521,15 +574,11 @@ static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BP
}
}
-static void do_lasso_select_curve(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
{
LassoSelectUserData data;
- /* set vc->editnurb */
- data.vc = vc;
- data.mcords = mcords;
- data.moves = moves;
- data.select = select;
+ view3d_userdata_lassoselect_init(&data, vc, NULL, mcords, moves, select);
if (extend == 0 && select)
CU_deselect_all(vc->obedit);
@@ -546,14 +595,11 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x,
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
}
}
-static void do_lasso_select_lattice(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
{
LassoSelectUserData data;
- /* set editdata in vc */
- data.mcords = mcords;
- data.moves = moves;
- data.select = select;
+ view3d_userdata_lassoselect_init(&data, vc, NULL, mcords, moves, select);
if (extend == 0 && select)
ED_setflagsLatt(vc->obedit, 0);
@@ -562,51 +608,70 @@ static void do_lasso_select_lattice(ViewContext *vc, int mcords[][2], short move
lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data);
}
-static void do_lasso_select_armature(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBone *ebone, int x0, int y0, int x1, int y1)
{
- bArmature *arm = vc->obedit->data;
- EditBone *ebone;
- float vec[3];
- short sco1[2], sco2[2], didpoint;
- int change = FALSE;
+ LassoSelectUserData *data = userData;
+ bArmature *arm = data->vc->obedit->data;
- if (extend == 0 && select)
- ED_armature_deselect_all_visible(vc->obedit);
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ int is_point_done = FALSE;
+ int points_proj_tot = 0;
- /* set editdata in vc */
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) {
- mul_v3_m4v3(vec, vc->obedit->obmat, ebone->head);
- ED_view3d_project_short(vc->ar, vec, sco1);
- mul_v3_m4v3(vec, vc->obedit->obmat, ebone->tail);
- ED_view3d_project_short(vc->ar, vec, sco2);
-
- didpoint = 0;
- if (BLI_lasso_is_point_inside(mcords, moves, sco1[0], sco1[1], IS_CLIPPED)) {
- if (select) ebone->flag |= BONE_ROOTSEL;
- else ebone->flag &= ~BONE_ROOTSEL;
- didpoint = 1;
- change = TRUE;
- }
- if (BLI_lasso_is_point_inside(mcords, moves, sco2[0], sco2[1], IS_CLIPPED)) {
- if (select) ebone->flag |= BONE_TIPSEL;
- else ebone->flag &= ~BONE_TIPSEL;
- didpoint = 1;
- change = TRUE;
+ /* project head location to screenspace */
+ if (x0 != IS_CLIPPED) {
+ points_proj_tot++;
+ if (BLI_rcti_isect_pt(data->rect, x0, y0) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX))
+ {
+ is_point_done = TRUE;
+ if (data->select) ebone->flag |= BONE_ROOTSEL;
+ else ebone->flag &= ~BONE_ROOTSEL;
}
- /* if one of points selected, we skip the bone itself */
- if (didpoint == 0 &&
- BLI_lasso_is_edge_inside(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1], IS_CLIPPED))
+ }
+
+ /* project tail location to screenspace */
+ if (x1 != IS_CLIPPED) {
+ points_proj_tot++;
+ if (BLI_rcti_isect_pt(data->rect, x1, y1) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX))
{
- if (select) ebone->flag |= BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED;
- else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- change = TRUE;
+ is_point_done = TRUE;
+ if (data->select) ebone->flag |= BONE_TIPSEL;
+ else ebone->flag &= ~BONE_TIPSEL;
}
}
+
+ /* if one of points selected, we skip the bone itself */
+ if ((is_point_done == FALSE) && (points_proj_tot == 2) &&
+ BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX))
+ {
+ if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ data->is_change = TRUE;
+ }
+
+ data->is_change |= is_point_done;
}
-
- if (change) {
+}
+
+static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
+{
+ LassoSelectUserData data;
+ rcti rect;
+
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ if (extend == 0 && select)
+ ED_armature_deselect_all_visible(vc->obedit);
+
+ armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data);
+
+ if (data.is_change) {
+ bArmature *arm = vc->obedit->data;
ED_armature_sync_selection(arm->edbo);
ED_armature_validate_active(arm);
WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
@@ -614,29 +679,29 @@ static void do_lasso_select_armature(ViewContext *vc, int mcords[][2], short mov
}
-
-
-static void do_lasso_select_meta(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
{
MetaBall *mb = (MetaBall *)vc->obedit->data;
MetaElem *ml;
- float vec[3];
- short sco[2];
if (extend == 0 && select) {
+ /* XXX, make an editor function as is done elsewhere */
for (ml = mb->editelems->first; ml; ml = ml->next) {
ml->flag &= ~SELECT;
}
}
- for (ml = mb->editelems->first; ml; ml = ml->next) {
-
- mul_v3_m4v3(vec, vc->obedit->obmat, &ml->x);
- ED_view3d_project_short(vc->ar, vec, sco);
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- if (BLI_lasso_is_point_inside(mcords, moves, sco[0], sco[1], IS_CLIPPED)) {
- if (select) ml->flag |= SELECT;
- else ml->flag &= ~SELECT;
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ int screen_co[2];
+ if (ED_view3d_project_int_object(vc->ar, &ml->x, screen_co,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+ {
+ if (BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) {
+ if (select) ml->flag |= SELECT;
+ else ml->flag &= ~SELECT;
+ }
}
}
}
@@ -700,7 +765,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int
return OPERATOR_FINISHED;
}
-static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
{
Object *ob = vc->obact;
Mesh *me = ob ? ob->data : NULL;
@@ -722,7 +787,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short mo
paintvert_flush_flags(ob);
}
-static void do_lasso_select_paintface(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
{
Object *ob = vc->obact;
Mesh *me = ob ? ob->data : NULL;
@@ -777,7 +842,9 @@ static void do_lasso_select_node(int mcords[][2], short moves, short select)
}
#endif
-static void view3d_lasso_select(bContext *C, ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+static void view3d_lasso_select(bContext *C, ViewContext *vc,
+ const int mcords[][2], short moves,
+ short extend, short select)
{
Object *ob = CTX_data_active_object(C);
@@ -828,7 +895,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
{
ViewContext vc;
int mcords_tot;
- int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+ const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
if (mcords) {
short extend, select;
@@ -1059,8 +1126,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
}
else {
int temp, dist = 15;
-
- ED_view3d_project_short(vc->ar, base->object->obmat[3], &base->sx);
+ ED_view3d_project_base(vc->ar, base);
temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]);
if (temp < dist)
@@ -1341,8 +1407,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
base = startbase;
while (base) {
if (BASE_SELECTABLE(v3d, base)) {
- ED_view3d_project_short(ar, base->object->obmat[3], &base->sx);
-
+ ED_view3d_project_base(ar, base);
temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]);
if (base == BASACT) temp += 10;
if (temp < dist) {
@@ -1513,19 +1578,37 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
typedef struct BoxSelectUserData {
ViewContext *vc;
- rcti *rect;
- int select, pass, done;
+ const rcti *rect;
+ int select;
+
+ /* runtime */
+ int pass;
+ int is_done;
+ int is_change;
} BoxSelectUserData;
-int edge_inside_circle(int centx, int centy, int rad, int x1, int y1, int x2, int y2)
+static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
+ ViewContext *vc, const rcti *rect, const int select)
+{
+ r_data->vc = vc;
+ r_data->rect = rect;
+ r_data->select = select;
+
+ /* runtime */
+ r_data->pass = 0;
+ r_data->is_done = FALSE;
+ r_data->is_change = FALSE;
+}
+
+int edge_inside_circle(int centx, int centy, int radius, int x1, int y1, int x2, int y2)
{
- int radsq = rad * rad;
+ int radius_squared = radius * radius;
/* check points in circle itself */
- if ((x1 - centx) * (x1 - centx) + (y1 - centy) * (y1 - centy) <= radsq) {
+ if ((x1 - centx) * (x1 - centx) + (y1 - centy) * (y1 - centy) <= radius_squared) {
return TRUE;
}
- else if ((x2 - centx) * (x2 - centx) + (y2 - centy) * (y2 - centy) <= radsq) {
+ else if ((x2 - centx) * (x2 - centx) + (y2 - centy) * (y2 - centy) <= radius_squared) {
return TRUE;
}
else {
@@ -1533,7 +1616,7 @@ int edge_inside_circle(int centx, int centy, int rad, int x1, int y1, int x2, in
const float v1[2] = {x1, y1};
const float v2[2] = {x2, y2};
/* pointdistline */
- if (dist_squared_to_line_segment_v2(cent, v1, v2) < (float)radsq) {
+ if (dist_squared_to_line_segment_v2(cent, v1, v2) < (float)radius_squared) {
return TRUE;
}
}
@@ -1577,9 +1660,7 @@ static int do_nurbs_box_select(ViewContext *vc, rcti *rect, int select, int exte
{
BoxSelectUserData data;
- data.vc = vc;
- data.rect = rect;
- data.select = select;
+ view3d_userdata_boxselect_init(&data, vc, rect, select);
if (extend == 0 && select)
CU_deselect_all(vc->obedit);
@@ -1602,9 +1683,7 @@ static int do_lattice_box_select(ViewContext *vc, rcti *rect, int select, int ex
{
BoxSelectUserData data;
- data.vc = vc;
- data.rect = rect;
- data.select = select;
+ view3d_userdata_boxselect_init(&data, vc, rect, select);
if (extend == 0 && select)
ED_setflagsLatt(vc->obedit, 0);
@@ -1631,7 +1710,7 @@ static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, int x0
if (data->pass == 0) {
if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) {
BM_edge_select_set(data->vc->em->bm, eed, data->select);
- data->done = TRUE;
+ data->is_done = TRUE;
}
}
else {
@@ -1655,11 +1734,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten
ToolSettings *ts = vc->scene->toolsettings;
int bbsel;
- data.vc = vc;
- data.rect = rect;
- data.select = select;
- data.pass = 0;
- data.done = FALSE;
+ view3d_userdata_boxselect_init(&data, vc, rect, select);
if (extend == 0 && select)
EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
@@ -1684,7 +1759,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten
data.pass = 0;
mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_CLIP_TEST_OFF);
- if (data.done == 0) {
+ if (data.is_done == 0) {
data.pass = 1;
mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_CLIP_TEST_OFF);
}
@@ -2142,15 +2217,32 @@ typedef struct CircleSelectUserData {
short select;
int mval[2];
float radius;
+ float radius_squared;
+
+ /* runtime */
+ int is_change;
} CircleSelectUserData;
+static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
+ ViewContext *vc, const int select, const int mval[2], const float rad)
+{
+ r_data->vc = vc;
+ r_data->select = select;
+ copy_v2_v2_int(r_data->mval, mval);
+ r_data->radius = rad;
+ r_data->radius_squared = rad * rad;
+
+ /* runtime */
+ r_data->is_change = FALSE;
+}
+
static void mesh_circle_doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
{
CircleSelectUserData *data = userData;
- int mx = x - data->mval[0], my = y - data->mval[1];
- float r = sqrt(mx * mx + my * my);
+ const float delta[2] = {(float)(x - data->mval[0]),
+ (float)(y - data->mval[1])};
- if (r <= data->radius) {
+ if (len_squared_v2(delta) <= data->radius_squared) {
BM_vert_select_set(data->vc->em->bm, eve, data->select);
}
}
@@ -2165,10 +2257,10 @@ static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, int x0, int y0
static void mesh_circle_doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
{
CircleSelectUserData *data = userData;
- int mx = x - data->mval[0], my = y - data->mval[1];
- float r = sqrt(mx * mx + my * my);
-
- if (r <= data->radius) {
+ const float delta[2] = {(float)(x - data->mval[0]),
+ (float)(y - data->mval[1])};
+
+ if (len_squared_v2(delta) <= data->radius_squared) {
BM_face_select_set(data->vc->em->bm, efa, data->select);
}
}
@@ -2184,11 +2276,7 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f
vc->em = BMEdit_FromObject(vc->obedit);
- data.vc = vc;
- data.select = select;
- data.mval[0] = mval[0];
- data.mval[1] = mval[1];
- data.radius = rad;
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
if (ts->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
@@ -2259,12 +2347,13 @@ static void paint_vertsel_circle_select(ViewContext *vc, int select, const int m
static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
{
CircleSelectUserData *data = userData;
- int mx = x - data->mval[0], my = y - data->mval[1];
- float r = sqrt(mx * mx + my * my);
Object *obedit = data->vc->obedit;
Curve *cu = (Curve *)obedit->data;
- if (r <= data->radius) {
+ const float delta[2] = {(float)(x - data->mval[0]),
+ (float)(y - data->mval[1])};
+
+ if (len_squared_v2(delta) <= data->radius_squared) {
if (bp) {
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
@@ -2302,6 +2391,7 @@ static void nurbscurve_circle_select(ViewContext *vc, int select, const int mval
data.mval[1] = mval[1];
data.radius = rad;
data.vc = vc;
+ data.is_change = FALSE;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data);
@@ -2311,10 +2401,10 @@ static void nurbscurve_circle_select(ViewContext *vc, int select, const int mval
static void latticecurve_circle_doSelect(void *userData, BPoint *bp, int x, int y)
{
CircleSelectUserData *data = userData;
- int mx = x - data->mval[0], my = y - data->mval[1];
- float r = sqrt(mx * mx + my * my);
+ const float delta[2] = {(float)(x - data->mval[0]),
+ (float)(y - data->mval[1])};
- if (r <= data->radius) {
+ if (len_squared_v2(delta) <= data->radius_squared) {
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
}
}
@@ -2322,12 +2412,7 @@ static void lattice_circle_select(ViewContext *vc, int select, const int mval[2]
{
CircleSelectUserData data;
- /* set vc-> edit data */
-
- data.select = select;
- data.mval[0] = mval[0];
- data.mval[1] = mval[1];
- data.radius = rad;
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data);
@@ -2338,10 +2423,10 @@ static void lattice_circle_select(ViewContext *vc, int select, const int mval[2]
static short pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, int x, int y)
{
CircleSelectUserData *data = userData;
- int mx = x - data->mval[0], my = y - data->mval[1];
- float r = sqrt(mx * mx + my * my);
-
- if (r <= data->radius) {
+ const float delta[2] = {(float)(x - data->mval[0]),
+ (float)(y - data->mval[1])};
+
+ if (len_squared_v2(delta) <= data->radius_squared) {
if (data->select)
pchan->bone->flag |= BONE_SELECTED;
else
@@ -2350,63 +2435,78 @@ static short pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, int
}
return 0;
}
+static void do_circle_select_pose__doSelectBone(void *userData, struct bPoseChannel *pchan, int x0, int y0, int x1, int y1)
+{
+ CircleSelectUserData *data = userData;
+ bArmature *arm = data->vc->obact->data;
+
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ int is_point_done = FALSE;
+ int points_proj_tot = 0;
+
+ /* project head location to screenspace */
+ if (x0 != IS_CLIPPED) {
+ points_proj_tot++;
+ if (pchan_circle_doSelectJoint(data, pchan, x0, y0)) {
+ is_point_done = TRUE;
+ }
+ }
+
+ /* project tail location to screenspace */
+ if (x1 != IS_CLIPPED) {
+ points_proj_tot++;
+ if (pchan_circle_doSelectJoint(data, pchan, x1, y1)) {
+ is_point_done = TRUE;
+ }
+ }
+
+ /* check if the head and/or tail is in the circle
+ * - the call to check also does the selection already
+ */
+
+ /* only if the endpoints didn't get selected, deal with the middle of the bone too
+ * It works nicer to only do this if the head or tail are not in the circle,
+ * otherwise there is no way to circle select joints alone */
+ if ((is_point_done == FALSE) && (points_proj_tot == 2) &&
+ edge_inside_circle(data->mval[0], data->mval[1], data->radius, x0, y0, x1, y1))
+ {
+ if (data->select) pchan->bone->flag |= BONE_SELECTED;
+ else pchan->bone->flag &= ~BONE_SELECTED;
+ data->is_change = TRUE;
+ }
+
+ data->is_change |= is_point_done;
+ }
+}
static void pose_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
{
CircleSelectUserData data;
- bArmature *arm = vc->obact->data;
- bPose *pose = vc->obact->pose;
- bPoseChannel *pchan;
- int change = FALSE;
- /* set vc->edit data */
- data.select = select;
- data.mval[0] = mval[0];
- data.mval[1] = mval[1];
- data.radius = rad;
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
- /* check each PoseChannel... */
- /* TODO: could be optimized at some point */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- short sco1[2], sco2[2], didpoint = 0;
- float vec[3];
-
- /* skip invisible bones */
- if (PBONE_VISIBLE(arm, pchan->bone) == 0)
- continue;
-
- /* project head location to screenspace */
- mul_v3_m4v3(vec, vc->obact->obmat, pchan->pose_head);
- ED_view3d_project_short(vc->ar, vec, sco1);
-
- /* project tail location to screenspace */
- mul_v3_m4v3(vec, vc->obact->obmat, pchan->pose_tail);
- ED_view3d_project_short(vc->ar, vec, sco2);
-
- /* check if the head and/or tail is in the circle
- * - the call to check also does the selection already
- */
- if (pchan_circle_doSelectJoint(&data, pchan, sco1[0], sco1[1]))
- didpoint = 1;
- if (pchan_circle_doSelectJoint(&data, pchan, sco2[0], sco2[1]))
- didpoint = 1;
-
- change |= didpoint;
- }
+ pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data);
+
+ if (data.is_change) {
+ bArmature *arm = vc->obact->data;
- if (change) {
WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obact);
+
+ if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* mask modifier ('armature' mode), etc. */
+ DAG_id_tag_update(&vc->obact->id, OB_RECALC_DATA);
+ }
}
}
static short armature_circle_doSelectJoint(void *userData, EditBone *ebone, int x, int y, short head)
{
CircleSelectUserData *data = userData;
- int mx = x - data->mval[0], my = y - data->mval[1];
- float r = sqrt(mx * mx + my * my);
+ const float delta[2] = {(float)(x - data->mval[0]),
+ (float)(y - data->mval[1])};
- if (r <= data->radius) {
+ if (len_squared_v2(delta) <= data->radius_squared) {
if (head) {
if (data->select)
ebone->flag |= BONE_ROOTSEL;
@@ -2423,57 +2523,61 @@ static short armature_circle_doSelectJoint(void *userData, EditBone *ebone, int
}
return 0;
}
-static void armature_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
+static void do_circle_select_armature__doSelectBone(void *userData, struct EditBone *ebone, int x0, int y0, int x1, int y1)
{
- CircleSelectUserData data;
- bArmature *arm = vc->obedit->data;
- EditBone *ebone;
- int change = FALSE;
-
- /* set vc->edit data */
- data.select = select;
- data.mval[0] = mval[0];
- data.mval[1] = mval[1];
- data.radius = rad;
+ CircleSelectUserData *data = userData;
+ bArmature *arm = data->vc->obedit->data;
+
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ int is_point_done = FALSE;
+ int points_proj_tot = 0;
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
-
- /* check each EditBone... */
- /* TODO: could be optimized at some point */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- short sco1[2], sco2[2], didpoint = 0;
- float vec[3];
-
/* project head location to screenspace */
- mul_v3_m4v3(vec, vc->obedit->obmat, ebone->head);
- ED_view3d_project_short(vc->ar, vec, sco1);
-
+ if (x0 != IS_CLIPPED) {
+ points_proj_tot++;
+ if (armature_circle_doSelectJoint(data, ebone, x0, y0, TRUE)) {
+ is_point_done = TRUE;
+ }
+ }
+
/* project tail location to screenspace */
- mul_v3_m4v3(vec, vc->obedit->obmat, ebone->tail);
- ED_view3d_project_short(vc->ar, vec, sco2);
-
- /* check if the head and/or tail is in the circle
- * - the call to check also does the selection already
+ if (x1 != IS_CLIPPED) {
+ points_proj_tot++;
+ if (armature_circle_doSelectJoint(data, ebone, x1, y1, FALSE)) {
+ is_point_done = TRUE;
+ }
+ }
+
+ /* check if the head and/or tail is in the circle
+ * - the call to check also does the selection already
*/
- if (armature_circle_doSelectJoint(&data, ebone, sco1[0], sco1[1], 1))
- didpoint = 1;
- if (armature_circle_doSelectJoint(&data, ebone, sco2[0], sco2[1], 0))
- didpoint = 1;
-
- /* only if the endpoints didn't get selected, deal with the middle of the bone too */
- /* XXX should we just do this always? */
- if ((didpoint == 0) && edge_inside_circle(mval[0], mval[1], rad, sco1[0], sco1[1], sco2[0], sco2[1])) {
- if (select)
- ebone->flag |= BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED;
- else
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- change = TRUE;
+
+ /* only if the endpoints didn't get selected, deal with the middle of the bone too
+ * It works nicer to only do this if the head or tail are not in the circle,
+ * otherwise there is no way to circle select joints alone */
+ if ((is_point_done == FALSE) && (points_proj_tot == 2) &&
+ edge_inside_circle(data->mval[0], data->mval[1], data->radius, x0, y0, x1, y1))
+ {
+ if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ data->is_change = TRUE;
}
-
- change |= didpoint;
+
+ data->is_change |= is_point_done;
}
+}
+static void armature_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
+{
+ CircleSelectUserData data;
+ bArmature *arm = vc->obedit->data;
+
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ armature_foreachScreenBone(vc, do_circle_select_armature__doSelectBone, &data);
- if (change) {
+ if (data.is_change) {
ED_armature_sync_selection(arm->edbo);
ED_armature_validate_active(arm);
WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
@@ -2556,7 +2660,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
select = select ? BA_SELECT : BA_DESELECT;
for (base = FIRSTBASE; base; base = base->next) {
if (BASE_SELECTABLE(v3d, base)) {
- ED_view3d_project_short(ar, base->object->obmat[3], &base->sx);
+ ED_view3d_project_base(ar, base);
if (base->sx != IS_CLIPPED) {
int dx = base->sx - x;
int dy = base->sy - y;