doxygen: add newline after \file
[blender.git] / source / blender / editors / lattice / editlattice_select.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edlattice
22  */
23
24 #include <stdlib.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "BLI_listbase.h"
29 #include "BLI_math.h"
30 #include "BLI_utildefines.h"
31 #include "BLI_rand.h"
32 #include "BLI_bitmap.h"
33
34 #include "DNA_curve_types.h"
35 #include "DNA_lattice_types.h"
36 #include "DNA_meshdata_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39
40 #include "RNA_access.h"
41 #include "RNA_define.h"
42 #include "RNA_enum_types.h"
43
44 #include "BKE_context.h"
45 #include "BKE_lattice.h"
46 #include "BKE_report.h"
47 #include "BKE_layer.h"
48
49 #include "ED_object.h"
50 #include "ED_screen.h"
51 #include "ED_select_utils.h"
52 #include "ED_lattice.h"
53 #include "ED_view3d.h"
54
55 #include "WM_api.h"
56 #include "WM_types.h"
57
58 #include "DEG_depsgraph.h"
59
60 #include "lattice_intern.h"
61
62 /* -------------------------------------------------------------------- */
63 /** \name Utility Functions
64  * \{ */
65
66 static void bpoint_select_set(BPoint *bp, bool select)
67 {
68         if (select) {
69                 if (!bp->hide) {
70                         bp->f1 |= SELECT;
71                 }
72         }
73         else {
74                 bp->f1 &= ~SELECT;
75         }
76 }
77
78 /** \} */
79
80 /* -------------------------------------------------------------------- */
81 /** \name Select Random Operator
82  * \{ */
83
84 static int lattice_select_random_exec(bContext *C, wmOperator *op)
85 {
86         const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
87         const int seed = WM_operator_properties_select_random_seed_increment_get(op);
88         const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
89
90         ViewLayer *view_layer = CTX_data_view_layer(C);
91         uint objects_len = 0;
92         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
93         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
94                 Object *obedit = objects[ob_index];
95                 Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
96
97                 RNG *rng = BLI_rng_new_srandom(seed);
98
99                 int tot;
100                 BPoint *bp;
101
102                 tot = lt->pntsu * lt->pntsv * lt->pntsw;
103                 bp = lt->def;
104                 while (tot--) {
105                         if (!bp->hide) {
106                                 if (BLI_rng_get_float(rng) < randfac) {
107                                         bpoint_select_set(bp, select);
108                                 }
109                         }
110                         bp++;
111                 }
112
113                 if (select == false) {
114                         lt->actbp = LT_ACTBP_NONE;
115                 }
116
117                 BLI_rng_free(rng);
118
119                 DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
120                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
121
122         }
123         MEM_freeN(objects);
124
125         return OPERATOR_FINISHED;
126 }
127
128 void LATTICE_OT_select_random(wmOperatorType *ot)
129 {
130         /* identifiers */
131         ot->name = "Select Random";
132         ot->description = "Randomly select UVW control points";
133         ot->idname = "LATTICE_OT_select_random";
134
135         /* api callbacks */
136         ot->exec = lattice_select_random_exec;
137         ot->poll = ED_operator_editlattice;
138
139         /* flags */
140         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
141
142         /* props */
143         WM_operator_properties_select_random(ot);
144 }
145
146 /** \} */
147
148 /* -------------------------------------------------------------------- */
149 /** \name Select Mirror Operator
150  * \{ */
151
152 static void ed_lattice_select_mirrored(Lattice *lt, const int axis, const bool extend)
153 {
154         const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
155         int i;
156         BPoint *bp;
157         BLI_bitmap *selpoints;
158
159         bool flip_uvw[3] = {false};
160         flip_uvw[axis] = true;
161
162         /* we could flip this too */
163         if (!extend) {
164                 lt->actbp = LT_ACTBP_NONE;
165         }
166
167         /* store "original" selection */
168         selpoints = BLI_BITMAP_NEW(tot, __func__);
169         BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
170
171         /* actual (de)selection */
172         for (i = 0; i < tot; i++) {
173                 const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
174                 bp = &lt->def[i];
175                 if (!bp->hide) {
176                         if (BLI_BITMAP_TEST(selpoints, i_flip)) {
177                                 bp->f1 |= SELECT;
178                         }
179                         else {
180                                 if (!extend) {
181                                         bp->f1 &= ~SELECT;
182                                 }
183                         }
184                 }
185         }
186
187
188         MEM_freeN(selpoints);
189 }
190
191 static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
192 {
193         const int axis_flag = RNA_enum_get(op->ptr, "axis");
194         const bool extend = RNA_boolean_get(op->ptr, "extend");
195
196         ViewLayer *view_layer = CTX_data_view_layer(C);
197         uint objects_len = 0;
198         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
199
200         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
201                 Object *obedit = objects[ob_index];
202                 Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
203
204                 for (int axis = 0; axis < 3; axis++) {
205                         if ((1 << axis) & axis_flag) {
206                                 ed_lattice_select_mirrored(lt, axis, extend);
207                         }
208                 }
209
210                 /* TODO, only notify changes */
211                 DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
212                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
213         }
214         MEM_freeN(objects);
215
216         return OPERATOR_FINISHED;
217 }
218
219 void LATTICE_OT_select_mirror(wmOperatorType *ot)
220 {
221         /* identifiers */
222         ot->name = "Select Mirror";
223         ot->description = "Select mirrored lattice points";
224         ot->idname = "LATTICE_OT_select_mirror";
225
226         /* api callbacks */
227         ot->exec = lattice_select_mirror_exec;
228         ot->poll = ED_operator_editlattice;
229
230         /* flags */
231         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
232
233         /* props */
234         RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
235
236         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
237 }
238
239 /** \} */
240
241 /* -------------------------------------------------------------------- */
242 /** \name Select More/Less Operator
243  * \{ */
244
245 static bool lattice_test_bitmap_uvw(Lattice *lt, BLI_bitmap *selpoints, int u, int v, int w, const bool selected)
246 {
247         if ((u < 0 || u >= lt->pntsu) ||
248             (v < 0 || v >= lt->pntsv) ||
249             (w < 0 || w >= lt->pntsw))
250         {
251                 return false;
252         }
253         else {
254                 int i = BKE_lattice_index_from_uvw(lt, u, v, w);
255                 if (lt->def[i].hide == 0) {
256                         return (BLI_BITMAP_TEST(selpoints, i) != 0) == selected;
257                 }
258                 return false;
259         }
260 }
261
262 static int lattice_select_more_less(bContext *C, const bool select)
263 {
264         ViewLayer *view_layer = CTX_data_view_layer(C);
265         uint objects_len;
266         bool changed = false;
267
268         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
269         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
270                 Object *obedit = objects[ob_index];
271                 Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
272                 BPoint *bp;
273                 const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
274                 int u, v, w;
275                 BLI_bitmap *selpoints;
276
277                 lt->actbp = LT_ACTBP_NONE;
278
279                 selpoints = BLI_BITMAP_NEW(tot, __func__);
280                 BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
281
282                 bp = lt->def;
283                 for (w = 0; w < lt->pntsw; w++) {
284                         for (v = 0; v < lt->pntsv; v++) {
285                                 for (u = 0; u < lt->pntsu; u++) {
286                                         if ((bp->hide == 0) && (((bp->f1 & SELECT) == 0) == select)) {
287                                                 if (lattice_test_bitmap_uvw(lt, selpoints, u + 1, v, w, select) ||
288                                                     lattice_test_bitmap_uvw(lt, selpoints, u - 1, v, w, select) ||
289                                                     lattice_test_bitmap_uvw(lt, selpoints, u, v + 1, w, select) ||
290                                                     lattice_test_bitmap_uvw(lt, selpoints, u, v - 1, w, select) ||
291                                                     lattice_test_bitmap_uvw(lt, selpoints, u, v, w + 1, select) ||
292                                                     lattice_test_bitmap_uvw(lt, selpoints, u, v, w - 1, select))
293                                                 {
294                                                         SET_FLAG_FROM_TEST(bp->f1, select, SELECT);
295                                                 }
296                                         }
297                                         bp++;
298                                 }
299                         }
300                 }
301
302                 MEM_freeN(selpoints);
303
304                 changed = true;
305                 DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
306                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
307         }
308         MEM_freeN(objects);
309
310         return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
311 }
312
313 static int lattice_select_more_exec(bContext *C, wmOperator *UNUSED(op))
314 {
315         return lattice_select_more_less(C, true);
316 }
317
318 static int lattice_select_less_exec(bContext *C, wmOperator *UNUSED(op))
319 {
320         return lattice_select_more_less(C, false);
321 }
322
323 void LATTICE_OT_select_more(wmOperatorType *ot)
324 {
325         /* identifiers */
326         ot->name = "Select More";
327         ot->description = "Select vertex directly linked to already selected ones";
328         ot->idname = "LATTICE_OT_select_more";
329
330         /* api callbacks */
331         ot->exec = lattice_select_more_exec;
332         ot->poll = ED_operator_editlattice;
333
334         /* flags */
335         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
336 }
337
338 void LATTICE_OT_select_less(wmOperatorType *ot)
339 {
340         /* identifiers */
341         ot->name = "Select Less";
342         ot->description = "Deselect vertices at the boundary of each selection region";
343         ot->idname = "LATTICE_OT_select_less";
344
345         /* api callbacks */
346         ot->exec = lattice_select_less_exec;
347         ot->poll = ED_operator_editlattice;
348
349         /* flags */
350         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
351 }
352
353 /** \} */
354
355 /* -------------------------------------------------------------------- */
356 /** \name Select All Operator
357  * \{ */
358
359 void ED_lattice_flags_set(Object *obedit, int flag)
360 {
361         Lattice *lt = obedit->data;
362         BPoint *bp;
363         int a;
364
365         bp = lt->editlatt->latt->def;
366
367         a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
368         lt->editlatt->latt->actbp = LT_ACTBP_NONE;
369
370         while (a--) {
371                 if (bp->hide == 0) {
372                         bp->f1 = flag;
373                 }
374                 bp++;
375         }
376 }
377
378 static int lattice_select_all_exec(bContext *C, wmOperator *op)
379 {
380         ViewLayer *view_layer = CTX_data_view_layer(C);
381         int action = RNA_enum_get(op->ptr, "action");
382
383         uint objects_len = 0;
384         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
385
386         if (action == SEL_TOGGLE) {
387                 action = SEL_SELECT;
388                 for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
389                         Object *obedit = objects[ob_index];
390                         Lattice *lt = obedit->data;
391                         if (BKE_lattice_is_any_selected(lt->editlatt->latt)) {
392                                 action = SEL_DESELECT;
393                                 break;
394                         }
395                 }
396         }
397
398         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
399                 Object *obedit = objects[ob_index];
400                 Lattice *lt;
401                 BPoint *bp;
402                 int a;
403
404                 switch (action) {
405                         case SEL_SELECT:
406                                 ED_lattice_flags_set(obedit, 1);
407                                 break;
408                         case SEL_DESELECT:
409                                 ED_lattice_flags_set(obedit, 0);
410                                 break;
411                         case SEL_INVERT:
412                                 lt = obedit->data;
413                                 bp = lt->editlatt->latt->def;
414                                 a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
415                                 lt->editlatt->latt->actbp = LT_ACTBP_NONE;
416
417                                 while (a--) {
418                                         if (bp->hide == 0) {
419                                                 bp->f1 ^= SELECT;
420                                         }
421                                         bp++;
422                                 }
423                                 break;
424                 }
425                 DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
426                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
427         }
428         MEM_freeN(objects);
429
430
431         return OPERATOR_FINISHED;
432 }
433
434 void LATTICE_OT_select_all(wmOperatorType *ot)
435 {
436         /* identifiers */
437         ot->name = "(De)select All";
438         ot->description = "Change selection of all UVW control points";
439         ot->idname = "LATTICE_OT_select_all";
440
441         /* api callbacks */
442         ot->exec = lattice_select_all_exec;
443         ot->poll = ED_operator_editlattice;
444
445         /* flags */
446         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
447
448         WM_operator_properties_select_all(ot);
449 }
450
451 /** \} */
452
453 /* -------------------------------------------------------------------- */
454 /** \name Select Ungrouped Verts Operator
455  * \{ */
456
457 static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
458 {
459         ViewLayer *view_layer = CTX_data_view_layer(C);
460         uint objects_len;
461         const bool is_extend = RNA_boolean_get(op->ptr, "extend");
462         bool changed = false;
463
464         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
465         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
466                 Object *obedit = objects[ob_index];
467                 Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
468                 MDeformVert *dv;
469                 BPoint *bp;
470                 int a, tot;
471
472                 if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) {
473                         continue;
474                 }
475
476                 if (!is_extend) {
477                         ED_lattice_flags_set(obedit, 0);
478                 }
479
480                 dv = lt->dvert;
481                 tot = lt->pntsu * lt->pntsv * lt->pntsw;
482
483                 for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
484                         if (bp->hide == 0) {
485                                 if (dv->dw == NULL) {
486                                         bp->f1 |= SELECT;
487                                 }
488                         }
489                 }
490
491                 changed = true;
492                 DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
493                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
494         }
495         MEM_freeN(objects);
496
497         if (!changed) {
498                 BKE_report(op->reports,
499                            RPT_ERROR,
500                            objects_len > 1 ? "No weights/vertex groups on objects" :
501                                              "No weights/vertex groups on object");
502                 return OPERATOR_CANCELLED;
503         }
504         return OPERATOR_FINISHED;
505 }
506
507 void LATTICE_OT_select_ungrouped(wmOperatorType *ot)
508 {
509         /* identifiers */
510         ot->name = "Select Ungrouped";
511         ot->idname = "LATTICE_OT_select_ungrouped";
512         ot->description = "Select vertices without a group";
513
514         /* api callbacks */
515         ot->exec = lattice_select_ungrouped_exec;
516         ot->poll = ED_operator_editlattice;
517
518         /* flags */
519         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
520
521         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
522 }
523
524 /** \} */
525
526
527 /* -------------------------------------------------------------------- */
528 /** \name Select Picking API
529  *
530  * Here actual select happens,
531  * Gets called via generic mouse select operator.
532  * \{ */
533
534
535 static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2])
536 {
537         struct { BPoint *bp; float dist; int select; float mval_fl[2]; bool is_changed; } *data = userData;
538         float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
539
540         if ((bp->f1 & SELECT) && data->select)
541                 dist_test += 5.0f;
542
543         if (dist_test < data->dist) {
544                 data->dist = dist_test;
545                 data->bp = bp;
546                 data->is_changed = true;
547         }
548 }
549
550 static BPoint *findnearestLattvert(ViewContext *vc, int sel, Base **r_base)
551 {
552         /* (sel == 1): selected gets a disadvantage */
553         /* in nurb and bezt or bp the nearest is written */
554         /* return 0 1 2: handlepunt */
555         struct { BPoint *bp; float dist; int select; float mval_fl[2]; bool is_changed; } data = {NULL};
556
557         data.dist = ED_view3d_select_dist_px();
558         data.select = sel;
559         data.mval_fl[0] = vc->mval[0];
560         data.mval_fl[1] = vc->mval[1];
561
562         uint bases_len;
563         Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &bases_len);
564         for (uint base_index = 0; base_index < bases_len; base_index++) {
565                 Base *base = bases[base_index];
566                 data.is_changed = false;
567
568                 ED_view3d_viewcontext_init_object(vc, base->object);
569                 ED_view3d_init_mats_rv3d(base->object, vc->rv3d);
570                 lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
571
572                 if (data.is_changed) {
573                         *r_base = base;
574                 }
575         }
576         MEM_freeN(bases);
577         return data.bp;
578 }
579
580 bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
581 {
582         ViewContext vc;
583         BPoint *bp = NULL;
584         Base *basact = NULL;
585
586         ED_view3d_viewcontext_init(C, &vc);
587         vc.mval[0] = mval[0];
588         vc.mval[1] = mval[1];
589
590         bp = findnearestLattvert(&vc, true, &basact);
591         if (bp) {
592                 ED_view3d_viewcontext_init_object(&vc, basact->object);
593                 Lattice *lt = ((Lattice *)vc.obedit->data)->editlatt->latt;
594
595                 if (!extend && !deselect && !toggle) {
596                         uint objects_len = 0;
597                         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &objects_len);
598                         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
599                                 Object *ob = objects[ob_index];
600                                 ED_lattice_flags_set(ob, 0);
601
602                                 DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
603                                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
604                         }
605                         MEM_freeN(objects);
606                 }
607
608                 if (extend) {
609                         bp->f1 |= SELECT;
610                 }
611                 else if (deselect) {
612                         bp->f1 &= ~SELECT;
613                 }
614                 else if (toggle) {
615                         bp->f1 ^= SELECT;  /* swap */
616                 }
617                 else {
618                         ED_lattice_flags_set(vc.obedit, 0);
619                         bp->f1 |= SELECT;
620                 }
621
622                 if (bp->f1 & SELECT) {
623                         lt->actbp = bp - lt->def;
624                 }
625                 else {
626                         lt->actbp = LT_ACTBP_NONE;
627                 }
628
629                 if (vc.view_layer->basact != basact) {
630                         ED_object_base_activate(C, basact);
631                 }
632
633                 DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
634                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
635
636                 return true;
637         }
638
639         return false;
640 }
641
642 /** \} */