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.c206
1 files changed, 172 insertions, 34 deletions
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index e1bbc0e1545..ac9c32816dd 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -48,12 +48,9 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_lasso.h"
-#include "BLI_rect.h"
+#include "BLI_blenlib.h"
#include "BLI_rand.h"
#include "BLI_linklist.h"
-#include "BLI_listbase.h"
-#include "BLI_string.h"
#include "BLI_utildefines.h"
/* vertex box select */
@@ -322,6 +319,79 @@ static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
#define MOVES_GESTURE 50
#define MOVES_LASSO 500
+int lasso_inside(int mcords[][2], short moves, int sx, int sy)
+{
+ /* we do the angle rule, define that all added angles should be about zero or 2*PI */
+ float angletot = 0.0, len, dot, ang, cross, fp1[2], fp2[2];
+ int a;
+ int *p1, *p2;
+
+ if (sx == IS_CLIPPED)
+ return 0;
+
+ p1 = mcords[moves - 1];
+ p2 = mcords[0];
+
+ /* first vector */
+ fp1[0] = (float)(p1[0] - sx);
+ fp1[1] = (float)(p1[1] - sy);
+ len = sqrt(fp1[0] * fp1[0] + fp1[1] * fp1[1]);
+ fp1[0] /= len;
+ fp1[1] /= len;
+
+ for (a = 0; a < moves; a++) {
+ /* second vector */
+ fp2[0] = (float)(p2[0] - sx);
+ fp2[1] = (float)(p2[1] - sy);
+ len = sqrt(fp2[0] * fp2[0] + fp2[1] * fp2[1]);
+ fp2[0] /= len;
+ fp2[1] /= len;
+
+ /* dot and angle and cross */
+ dot = fp1[0] * fp2[0] + fp1[1] * fp2[1];
+ ang = fabs(saacos(dot));
+
+ cross = (float)((p1[1] - p2[1]) * (p1[0] - sx) + (p2[0] - p1[0]) * (p1[1] - sy));
+
+ if (cross < 0.0f) angletot -= ang;
+ else angletot += ang;
+
+ /* circulate */
+ fp1[0] = fp2[0]; fp1[1] = fp2[1];
+ p1 = p2;
+ p2 = mcords[a + 1];
+ }
+
+ if (fabs(angletot) > 4.0) return 1;
+ return 0;
+}
+
+/* edge version for lasso select. we assume boundbox check was done */
+int lasso_inside_edge(int mcords[][2], short moves, int x0, int y0, int x1, int y1)
+{
+ int v1[2], v2[2];
+ int a;
+
+ if (x0 == IS_CLIPPED || x1 == IS_CLIPPED)
+ return 0;
+
+ v1[0] = x0, v1[1] = y0;
+ v2[0] = x1, v2[1] = y1;
+
+ /* check points in lasso */
+ if (lasso_inside(mcords, moves, v1[0], v1[1])) return 1;
+ if (lasso_inside(mcords, moves, v2[0], v2[1])) return 1;
+
+ /* no points in lasso, so we have to intersect with lasso edge */
+
+ if (isect_line_line_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) return 1;
+ for (a = 0; a < moves - 1; a++) {
+ if (isect_line_line_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) return 1;
+ }
+
+ return 0;
+}
+
/* 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
@@ -342,7 +412,7 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, int mcords[][2], s
mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
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 (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_SELECTED;
}
@@ -371,7 +441,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 */
project_short(vc->ar, base->object->obmat[3], &base->sx);
- if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
+ if (lasso_inside(mcords, moves, base->sx, base->sy)) {
if (select) ED_base_object_select(base, BA_SELECT);
else ED_base_object_select(base, BA_DESELECT);
@@ -384,13 +454,26 @@ static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short move
}
}
+static void lasso_select_boundbox(rcti *rect, int mcords[][2], short moves)
+{
+ short a;
+
+ rect->xmin = rect->xmax = mcords[0][0];
+ rect->ymin = rect->ymax = mcords[0][1];
+
+ for (a = 1; a < moves; a++) {
+ if (mcords[a][0] < rect->xmin) rect->xmin = mcords[a][0];
+ else if (mcords[a][0] > rect->xmax) rect->xmax = mcords[a][0];
+ if (mcords[a][1] < rect->ymin) rect->ymin = mcords[a][1];
+ else if (mcords[a][1] > rect->ymax) rect->ymax = mcords[a][1];
+ }
+}
+
static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
{
LassoSelectUserData *data = userData;
- if (BLI_in_rcti(data->rect, x, y) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED))
- {
+ if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
BM_vert_select_set(data->vc->em->bm, eve, data->select);
}
}
@@ -401,15 +484,14 @@ static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int
if (EDBM_backbuf_check(bm_solidoffs + index)) {
if (data->pass == 0) {
if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, IS_CLIPPED) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, IS_CLIPPED))
- {
+ lasso_inside(data->mcords, data->moves, x0, y0) &&
+ lasso_inside(data->mcords, data->moves, x1, y1)) {
BM_edge_select_set(data->vc->em->bm, eed, data->select);
data->done = 1;
}
}
else {
- if (BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, IS_CLIPPED)) {
+ if (lasso_inside_edge(data->mcords, data->moves, x0, y0, x1, y1)) {
BM_edge_select_set(data->vc->em->bm, eed, data->select);
}
}
@@ -419,9 +501,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, int
{
LassoSelectUserData *data = userData;
- if (BLI_in_rcti(data->rect, x, y) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED))
- {
+ if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
BM_face_select_set(data->vc->em->bm, efa, data->select);
}
}
@@ -433,7 +513,7 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
rcti rect;
int bbsel;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ lasso_select_boundbox(&rect, mcords, moves);
/* set editmesh */
vc->em = BMEdit_FromObject(vc->obedit);
@@ -487,13 +567,73 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
EDBM_selectmode_flush(vc->em);
}
+/* BMESH_TODO */
+#if 0
+/* this is an exception in that its the only lasso that dosnt use the 3d view (uses space image view) */
+static void do_lasso_select_mesh_uv(int mcords[][2], short moves, short select)
+{
+ EditFace *efa;
+ MTFace *tf;
+ int screenUV[2], nverts, i, ok = 1;
+ rcti rect;
+
+ lasso_select_boundbox(&rect, mcords, moves);
+
+ if (draw_uvs_face_check()) { /* Face Center Sel */
+ float cent[2];
+ ok = 0;
+ for (efa = em->faces.first; efa; efa = efa->next) {
+ /* assume not touched */
+ efa->tmp.l = 0;
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if ((select) != (simaFaceSel_Check(efa, tf))) {
+ uv_center(tf->uv, cent, (void *)efa->v4);
+ uvco_to_areaco_noclip(cent, screenUV);
+ if (BLI_in_rcti(&rect, screenUV[0], screenUV[1]) && lasso_inside(mcords, moves, screenUV[0], screenUV[1])) {
+ efa->tmp.l = ok = 1;
+ }
+ }
+ }
+ /* (de)selects all tagged faces and deals with sticky modes */
+ if (ok)
+ uvface_setsel__internal(select);
+
+ }
+ else { /* Vert Sel*/
+ for (efa = em->faces.first; efa; efa = efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ nverts = efa->v4 ? 4 : 3;
+ for (i = 0; i < nverts; i++) {
+ if ((select) != (simaUVSel_Check(efa, tf, i))) {
+ uvco_to_areaco_noclip(tf->uv[i], screenUV);
+ if (BLI_in_rcti(&rect, screenUV[0], screenUV[1]) && lasso_inside(mcords, moves, screenUV[0], screenUV[1])) {
+ if (select) {
+ simaUVSel_Set(efa, tf, i);
+ }
+ else {
+ simaUVSel_UnSet(efa, tf, i);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (ok && G.sima->flag & SI_SYNC_UVSEL) {
+ if (select) EM_select_flush(vc->em);
+ else EM_deselect_flush(vc->em);
+ }
+}
+#endif
+
static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
{
LassoSelectUserData *data = userData;
Object *obedit = data->vc->obedit;
Curve *cu = (Curve *)obedit->data;
- if (BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED)) {
+ if (lasso_inside(data->mcords, data->moves, x, y)) {
if (bp) {
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
if (bp == cu->lastsel && !(bp->f1 & 1)) cu->lastsel = NULL;
@@ -541,7 +681,7 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x,
{
LassoSelectUserData *data = userData;
- if (BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED)) {
+ if (lasso_inside(data->mcords, data->moves, x, y)) {
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
}
}
@@ -582,22 +722,20 @@ static void do_lasso_select_armature(ViewContext *vc, int mcords[][2], short mov
project_short(vc->ar, vec, sco2);
didpoint = 0;
- if (BLI_lasso_is_point_inside(mcords, moves, sco1[0], sco1[1], IS_CLIPPED)) {
+ if (lasso_inside(mcords, moves, sco1[0], sco1[1])) {
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 (lasso_inside(mcords, moves, sco2[0], sco2[1])) {
if (select) ebone->flag |= BONE_TIPSEL;
else ebone->flag &= ~BONE_TIPSEL;
didpoint = 1;
change = TRUE;
}
/* 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))
- {
+ 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_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
change = TRUE;
@@ -633,7 +771,7 @@ static void do_lasso_select_meta(ViewContext *vc, int mcords[][2], short moves,
mul_v3_m4v3(vec, vc->obedit->obmat, &ml->x);
project_short(vc->ar, vec, sco);
- if (BLI_lasso_is_point_inside(mcords, moves, sco[0], sco[1], IS_CLIPPED)) {
+ if (lasso_inside(mcords, moves, sco[0], sco[1])) {
if (select) ml->flag |= SELECT;
else ml->flag &= ~SELECT;
}
@@ -712,7 +850,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short mo
paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
bm_vertoffs = me->totvert + 1; /* max index array */
- BLI_lasso_boundbox(&rect, mcords, moves);
+ lasso_select_boundbox(&rect, mcords, moves);
EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
edbm_backbuf_check_and_select_verts_obmode(me, select);
@@ -735,7 +873,7 @@ static void do_lasso_select_paintface(ViewContext *vc, int mcords[][2], short mo
bm_vertoffs = me->totpoly + 1; /* max index array */
- BLI_lasso_boundbox(&rect, mcords, moves);
+ lasso_select_boundbox(&rect, mcords, moves);
EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
edbm_backbuf_check_and_select_tfaces(me, select);
@@ -755,7 +893,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, short select)
short node_cent[2];
float node_centf[2];
- BLI_lasso_boundbox(&rect, mcords, moves);
+ lasso_select_boundbox(&rect, mcords, moves);
/* store selection in temp test flag */
for (node = snode->edittree->nodes.first; node; node = node->next) {
@@ -764,7 +902,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, short select)
node_centf[1] = (node->totr.ymin + node->totr.ymax) / 2;
ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
- if (BLI_in_rcti(&rect, node_cent[0], node_cent[1]) && BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])) {
+ if (BLI_in_rcti(&rect, node_cent[0], node_cent[1]) && lasso_inside(mcords, moves, node_cent[0], node_cent[1])) {
if (select) {
node->flag |= SELECT;
}
@@ -830,7 +968,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
int i = 0;
int mcords[1024][2];
- RNA_BEGIN (op->ptr, itemptr, "path") {
+ RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
@@ -975,7 +1113,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
const char *name = object_mouse_select_menu_data[name_index].idname;
if (!extend) {
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ CTX_DATA_BEGIN(C, Base *, base, selectable_bases) {
if (base->flag & SELECT) {
ED_base_object_select(base, BA_DESELECT);
changed = 1;
@@ -984,7 +1122,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
}
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ CTX_DATA_BEGIN(C, Base *, base, selectable_bases) {
/* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */
if (strcmp(name, base->object->id.name + 2) == 0) {
ED_base_object_activate(C, base);
@@ -1051,7 +1189,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
short ok;
LinkNode *linklist = NULL;
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ CTX_DATA_BEGIN(C, Base *, base, selectable_bases) {
ok = FALSE;
/* two selection methods, the CTRL select uses max dist of 15 */
@@ -1829,7 +1967,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i
if (extend == 0 && select) {
if (bone_only) {
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) {
+ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) {
if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}