Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / object / object_lattice.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/object/object_lattice.c
27  *  \ingroup edobj
28  */
29
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BLI_listbase.h"
38 #include "BLI_math.h"
39 #include "BLI_utildefines.h"
40 #include "BLI_rand.h"
41 #include "BLI_bitmap.h"
42
43 #include "DNA_curve_types.h"
44 #include "DNA_key_types.h"
45 #include "DNA_lattice_types.h"
46 #include "DNA_meshdata_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_scene_types.h"
49
50 #include "RNA_access.h"
51 #include "RNA_define.h"
52 #include "RNA_enum_types.h"
53
54 #include "BKE_context.h"
55 #include "BKE_key.h"
56 #include "BKE_lattice.h"
57 #include "BKE_deform.h"
58 #include "BKE_report.h"
59 #include "BKE_utildefines.h"
60
61 #include "DEG_depsgraph.h"
62
63 #include "ED_lattice.h"
64 #include "ED_object.h"
65 #include "ED_screen.h"
66 #include "ED_view3d.h"
67 #include "ED_util.h"
68
69 #include "WM_api.h"
70 #include "WM_types.h"
71
72 #include "object_intern.h"
73
74 /********************** Load/Make/Free ********************/
75
76 void ED_lattice_editlatt_free(Object *ob)
77 {
78         Lattice *lt = ob->data;
79         
80         if (lt->editlatt) {
81                 Lattice *editlt = lt->editlatt->latt;
82
83                 if (editlt->def)
84                         MEM_freeN(editlt->def);
85                 if (editlt->dvert)
86                         BKE_defvert_array_free(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
87
88                 MEM_freeN(editlt);
89                 MEM_freeN(lt->editlatt);
90
91                 lt->editlatt = NULL;
92         }
93 }
94
95 void ED_lattice_editlatt_make(Object *obedit)
96 {
97         Lattice *lt = obedit->data;
98         KeyBlock *actkey;
99
100         ED_lattice_editlatt_free(obedit);
101
102         actkey = BKE_keyblock_from_object(obedit);
103         if (actkey)
104                 BKE_keyblock_convert_to_lattice(actkey, lt);
105
106         lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt");
107         lt->editlatt->latt = MEM_dupallocN(lt);
108         lt->editlatt->latt->def = MEM_dupallocN(lt->def);
109
110         if (lt->dvert) {
111                 int tot = lt->pntsu * lt->pntsv * lt->pntsw;
112                 lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
113                 BKE_defvert_array_copy(lt->editlatt->latt->dvert, lt->dvert, tot);
114         }
115
116         if (lt->key) lt->editlatt->shapenr = obedit->shapenr;
117 }
118
119 void ED_lattice_editlatt_load(Object *obedit)
120 {
121         Lattice *lt, *editlt;
122         KeyBlock *actkey;
123         BPoint *bp;
124         float *fp;
125         int tot;
126
127         lt = obedit->data;
128         editlt = lt->editlatt->latt;
129
130         if (lt->editlatt->shapenr) {
131                 actkey = BLI_findlink(&lt->key->block, lt->editlatt->shapenr - 1);
132
133                 /* active key: vertices */
134                 tot = editlt->pntsu * editlt->pntsv * editlt->pntsw;
135                 
136                 if (actkey->data) MEM_freeN(actkey->data);
137                 
138                 fp = actkey->data = MEM_callocN(lt->key->elemsize * tot, "actkey->data");
139                 actkey->totelem = tot;
140
141                 bp = editlt->def;
142                 while (tot--) {
143                         copy_v3_v3(fp, bp->vec);
144                         fp += 3;
145                         bp++;
146                 }
147         }
148         else {
149                 MEM_freeN(lt->def);
150
151                 lt->def = MEM_dupallocN(editlt->def);
152
153                 lt->flag = editlt->flag;
154
155                 lt->pntsu = editlt->pntsu;
156                 lt->pntsv = editlt->pntsv;
157                 lt->pntsw = editlt->pntsw;
158                 
159                 lt->typeu = editlt->typeu;
160                 lt->typev = editlt->typev;
161                 lt->typew = editlt->typew;
162                 lt->actbp = editlt->actbp;
163         }
164
165         if (lt->dvert) {
166                 BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
167                 lt->dvert = NULL;
168         }
169
170         if (editlt->dvert) {
171                 tot = lt->pntsu * lt->pntsv * lt->pntsw;
172
173                 lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
174                 BKE_defvert_array_copy(lt->dvert, editlt->dvert, tot);
175         }
176 }
177
178 static void bpoint_select_set(BPoint *bp, bool select)
179 {
180         if (select) {
181                 if (!bp->hide) {
182                         bp->f1 |= SELECT;
183                 }
184         }
185         else {
186                 bp->f1 &= ~SELECT;
187         }
188 }
189
190 /************************** Select Random Operator **********************/
191
192 static int lattice_select_random_exec(bContext *C, wmOperator *op)
193 {
194         Object *obedit = CTX_data_edit_object(C);
195         Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
196
197         const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
198         const int seed = WM_operator_properties_select_random_seed_increment_get(op);
199         const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
200
201         RNG *rng = BLI_rng_new_srandom(seed);
202
203         int tot;
204         BPoint *bp;
205
206         tot = lt->pntsu * lt->pntsv * lt->pntsw;
207         bp = lt->def;
208         while (tot--) {
209                 if (!bp->hide) {
210                         if (BLI_rng_get_float(rng) < randfac) {
211                                 bpoint_select_set(bp, select);
212                         }
213                 }
214                 bp++;
215         }
216
217         if (select == false) {
218                 lt->actbp = LT_ACTBP_NONE;
219         }
220
221         BLI_rng_free(rng);
222
223         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
224
225         return OPERATOR_FINISHED;
226 }
227
228 void LATTICE_OT_select_random(wmOperatorType *ot)
229 {
230         /* identifiers */
231         ot->name = "Select Random";
232         ot->description = "Randomly select UVW control points";
233         ot->idname = "LATTICE_OT_select_random";
234
235         /* api callbacks */
236         ot->exec = lattice_select_random_exec;
237         ot->poll = ED_operator_editlattice;
238
239         /* flags */
240         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
241
242         /* props */
243         WM_operator_properties_select_random(ot);
244 }
245
246
247 /* -------------------------------------------------------------------- */
248 /* Select Mirror Operator */
249
250 static void ed_lattice_select_mirrored(Lattice *lt, const int axis, const bool extend)
251 {
252         const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
253         int i;
254         BPoint *bp;
255         BLI_bitmap *selpoints;
256
257         bool flip_uvw[3] = {false};
258         flip_uvw[axis] = true;
259
260         /* we could flip this too */
261         if (!extend) {
262                 lt->actbp = LT_ACTBP_NONE;
263         }
264
265         /* store "original" selection */
266         selpoints = BLI_BITMAP_NEW(tot, __func__);
267         BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
268
269         /* actual (de)selection */
270         for (i = 0; i < tot; i++) {
271                 const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
272                 bp = &lt->def[i];
273                 if (!bp->hide) {
274                         if (BLI_BITMAP_TEST(selpoints, i_flip)) {
275                                 bp->f1 |= SELECT;
276                         }
277                         else {
278                                 if (!extend) {
279                                         bp->f1 &= ~SELECT;
280                                 }
281                         }
282                 }
283         }
284
285
286         MEM_freeN(selpoints);
287 }
288
289 static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
290 {
291         Object *obedit = CTX_data_edit_object(C);
292         Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
293         const int axis_flag = RNA_enum_get(op->ptr, "axis");
294         const bool extend = RNA_boolean_get(op->ptr, "extend");
295
296         for (int axis = 0; axis < 3; axis++) {
297                 if ((1 << axis) & axis_flag) {
298                         ed_lattice_select_mirrored(lt, axis, extend);
299                 }
300         }
301
302         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
303
304         return OPERATOR_FINISHED;
305 }
306
307 void LATTICE_OT_select_mirror(wmOperatorType *ot)
308 {
309         /* identifiers */
310         ot->name = "Select Mirror";
311         ot->description = "Select mirrored lattice points";
312         ot->idname = "LATTICE_OT_select_mirror";
313
314         /* api callbacks */
315         ot->exec = lattice_select_mirror_exec;
316         ot->poll = ED_operator_editlattice;
317
318         /* flags */
319         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
320
321         /* props */
322         RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
323
324         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
325 }
326
327
328 /************************** Select More/Less Operator *************************/
329
330 static bool lattice_test_bitmap_uvw(Lattice *lt, BLI_bitmap *selpoints, int u, int v, int w, const bool selected)
331 {
332         if ((u < 0 || u >= lt->pntsu) ||
333             (v < 0 || v >= lt->pntsv) ||
334             (w < 0 || w >= lt->pntsw))
335         {
336                 return false;
337         }
338         else {
339                 int i = BKE_lattice_index_from_uvw(lt, u, v, w);
340                 if (lt->def[i].hide == 0) {
341                         return (BLI_BITMAP_TEST(selpoints, i) != 0) == selected;
342                 }
343                 return false;
344         }
345 }
346
347 static int lattice_select_more_less(bContext *C, const bool select)
348 {
349         Object *obedit = CTX_data_edit_object(C);
350         Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
351         BPoint *bp;
352         const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
353         int u, v, w;
354         BLI_bitmap *selpoints;
355
356         lt->actbp = LT_ACTBP_NONE;
357
358         selpoints = BLI_BITMAP_NEW(tot, __func__);
359         BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
360
361         bp = lt->def;
362         for (w = 0; w < lt->pntsw; w++) {
363                 for (v = 0; v < lt->pntsv; v++) {
364                         for (u = 0; u < lt->pntsu; u++) {
365                                 if ((bp->hide == 0) && (((bp->f1 & SELECT) == 0) == select)) {
366                                         if (lattice_test_bitmap_uvw(lt, selpoints, u + 1, v, w, select) ||
367                                             lattice_test_bitmap_uvw(lt, selpoints, u - 1, v, w, select) ||
368                                             lattice_test_bitmap_uvw(lt, selpoints, u, v + 1, w, select) ||
369                                             lattice_test_bitmap_uvw(lt, selpoints, u, v - 1, w, select) ||
370                                             lattice_test_bitmap_uvw(lt, selpoints, u, v, w + 1, select) ||
371                                             lattice_test_bitmap_uvw(lt, selpoints, u, v, w - 1, select))
372                                         {
373                                                 BKE_BIT_TEST_SET(bp->f1, select, SELECT);
374                                         }
375                                 }
376                                 bp++;
377                         }
378                 }
379         }
380
381         MEM_freeN(selpoints);
382
383         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
384         return OPERATOR_FINISHED;
385 }
386
387 static int lattice_select_more_exec(bContext *C, wmOperator *UNUSED(op))
388 {
389         return lattice_select_more_less(C, true);
390 }
391
392 static int lattice_select_less_exec(bContext *C, wmOperator *UNUSED(op))
393 {
394         return lattice_select_more_less(C, false);
395 }
396
397 void LATTICE_OT_select_more(wmOperatorType *ot)
398 {
399         /* identifiers */
400         ot->name = "Select More";
401         ot->description = "Select vertex directly linked to already selected ones";
402         ot->idname = "LATTICE_OT_select_more";
403
404         /* api callbacks */
405         ot->exec = lattice_select_more_exec;
406         ot->poll = ED_operator_editlattice;
407
408         /* flags */
409         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
410 }
411
412 void LATTICE_OT_select_less(wmOperatorType *ot)
413 {
414         /* identifiers */
415         ot->name = "Select Less";
416         ot->description = "Deselect vertices at the boundary of each selection region";
417         ot->idname = "LATTICE_OT_select_less";
418
419         /* api callbacks */
420         ot->exec = lattice_select_less_exec;
421         ot->poll = ED_operator_editlattice;
422
423         /* flags */
424         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
425 }
426
427 /************************** Select All Operator *************************/
428
429 void ED_lattice_flags_set(Object *obedit, int flag)
430 {
431         Lattice *lt = obedit->data;
432         BPoint *bp;
433         int a;
434         
435         bp = lt->editlatt->latt->def;
436         
437         a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
438         lt->editlatt->latt->actbp = LT_ACTBP_NONE;
439
440         while (a--) {
441                 if (bp->hide == 0) {
442                         bp->f1 = flag;
443                 }
444                 bp++;
445         }
446 }
447
448 static int lattice_select_all_exec(bContext *C, wmOperator *op)
449 {
450         Object *obedit = CTX_data_edit_object(C);
451         Lattice *lt = obedit->data;
452         BPoint *bp;
453         int a;
454         int action = RNA_enum_get(op->ptr, "action");
455
456         if (action == SEL_TOGGLE) {
457                 action = SEL_SELECT;
458
459                 bp = lt->editlatt->latt->def;
460                 a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
461
462                 while (a--) {
463                         if (bp->hide == 0) {
464                                 if (bp->f1 & SELECT) {
465                                         action = SEL_DESELECT;
466                                         break;
467                                 }
468                         }
469                         bp++;
470                 }
471         }
472
473         switch (action) {
474                 case SEL_SELECT:
475                         ED_lattice_flags_set(obedit, 1);
476                         break;
477                 case SEL_DESELECT:
478                         ED_lattice_flags_set(obedit, 0);
479                         break;
480                 case SEL_INVERT:
481                         bp = lt->editlatt->latt->def;
482                         a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
483                         lt->editlatt->latt->actbp = LT_ACTBP_NONE;
484
485                         while (a--) {
486                                 if (bp->hide == 0) {
487                                         bp->f1 ^= SELECT;
488                                 }
489                                 bp++;
490                         }
491                         break;
492         }
493
494         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
495
496         return OPERATOR_FINISHED;
497 }
498
499 void LATTICE_OT_select_all(wmOperatorType *ot)
500 {
501         /* identifiers */
502         ot->name = "(De)select All";
503         ot->description = "Change selection of all UVW control points";
504         ot->idname = "LATTICE_OT_select_all";
505         
506         /* api callbacks */
507         ot->exec = lattice_select_all_exec;
508         ot->poll = ED_operator_editlattice;
509         
510         /* flags */
511         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
512
513         WM_operator_properties_select_all(ot);
514 }
515
516 /************************** Select Ungrouped Verts Operator *************************/
517
518 static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
519 {
520         Object *obedit = CTX_data_edit_object(C);
521         Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
522         MDeformVert *dv;
523         BPoint *bp;
524         int a, tot;
525
526         if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) {
527                 BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
528                 return OPERATOR_CANCELLED;
529         }
530
531         if (!RNA_boolean_get(op->ptr, "extend")) {
532                 ED_lattice_flags_set(obedit, 0);
533         }
534
535         dv = lt->dvert;
536         tot = lt->pntsu * lt->pntsv * lt->pntsw;
537
538         for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
539                 if (bp->hide == 0) {
540                         if (dv->dw == NULL) {
541                                 bp->f1 |= SELECT;
542                         }
543                 }
544         }
545
546         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
547
548         return OPERATOR_FINISHED;
549 }
550
551 void LATTICE_OT_select_ungrouped(wmOperatorType *ot)
552 {
553         /* identifiers */
554         ot->name = "Select Ungrouped";
555         ot->idname = "LATTICE_OT_select_ungrouped";
556         ot->description = "Select vertices without a group";
557
558         /* api callbacks */
559         ot->exec = lattice_select_ungrouped_exec;
560         ot->poll = ED_operator_editlattice;
561
562         /* flags */
563         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
564
565         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
566 }
567
568 /************************** Make Regular Operator *************************/
569
570 static int make_regular_poll(bContext *C)
571 {
572         Object *ob;
573
574         if (ED_operator_editlattice(C)) return 1;
575
576         ob = CTX_data_active_object(C);
577         return (ob && ob->type == OB_LATTICE);
578 }
579
580 static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
581 {
582         Object *ob = CTX_data_edit_object(C);
583         Lattice *lt;
584         
585         if (ob) {
586                 lt = ob->data;
587                 BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
588         }
589         else {
590                 ob = CTX_data_active_object(C);
591                 lt = ob->data;
592                 BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
593         }
594         
595         DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
596         WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
597
598         return OPERATOR_FINISHED;
599 }
600
601 void LATTICE_OT_make_regular(wmOperatorType *ot)
602 {
603         /* identifiers */
604         ot->name = "Make Regular";
605         ot->description = "Set UVW control points a uniform distance apart";
606         ot->idname = "LATTICE_OT_make_regular";
607         
608         /* api callbacks */
609         ot->exec = make_regular_exec;
610         ot->poll = make_regular_poll;
611         
612         /* flags */
613         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
614 }
615
616 /************************** Flip Verts Operator *************************/
617
618 /* flipping options */
619 typedef enum eLattice_FlipAxes {
620         LATTICE_FLIP_U = 0,
621         LATTICE_FLIP_V = 1,
622         LATTICE_FLIP_W = 2
623 } eLattice_FlipAxes;
624
625 /* Flip midpoint value so that relative distances between midpoint and neighbor-pair is maintained
626  * ! Assumes that uvw <=> xyz (i.e. axis-aligned index-axes with coordinate-axes)
627  * - Helper for lattice_flip_exec()
628  */
629 static void lattice_flip_point_value(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
630 {
631         BPoint *bp;
632         float diff;
633         
634         /* just the point in the middle (unpaired) */
635         bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
636         
637         /* flip over axis */
638         diff = mid - bp->vec[axis];
639         bp->vec[axis] = mid + diff;
640 }
641
642 /* Swap pairs of lattice points along a specified axis
643  * - Helper for lattice_flip_exec()
644  */
645 static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
646 {
647         BPoint *bpA, *bpB;
648         
649         int numU = lt->pntsu;
650         int numV = lt->pntsv;
651         int numW = lt->pntsw;
652         
653         int u0 = u, u1 = u;
654         int v0 = v, v1 = v;
655         int w0 = w, w1 = w;
656         
657         /* get pair index by just overriding the relevant pair-value
658          * - "-1" else buffer overflow
659          */
660         switch (axis) {
661                 case LATTICE_FLIP_U:
662                         u1 = numU - u - 1;
663                         break;
664                 case LATTICE_FLIP_V:
665                         v1 = numV - v - 1;
666                         break;
667                 case LATTICE_FLIP_W:
668                         w1 = numW - w - 1;
669                         break;
670         }
671         
672         /* get points to operate on */
673         bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
674         bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
675         
676         /* Swap all coordinates, so that flipped coordinates belong to
677          * the indices on the correct side of the lattice.
678          *
679          *   Coords:  (-2 4) |0| (3 4)   --> (3 4) |0| (-2 4) 
680          *   Indices:  (0,L)     (1,R)   --> (0,L)     (1,R)
681          */
682         swap_v3_v3(bpA->vec, bpB->vec);
683         
684         /* However, we need to mirror the coordinate values on the axis we're dealing with,
685          * otherwise we'd have effectively only rotated the points around. If we don't do this,
686          * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
687          * such as flipped normals, etc.
688          *
689          *   Coords:  (3 4) |0| (-2 4)  --\   
690          *                                 \-> (-3 4) |0| (2 4)
691          *   Indices: (0,L)     (1,R)   -->     (0,L)     (1,R)
692          */
693         lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
694         lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
695 }
696         
697 static int lattice_flip_exec(bContext *C, wmOperator *op)
698 {
699         Object *obedit = CTX_data_edit_object(C);
700         Lattice *lt;
701         
702         eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
703         int numU, numV, numW;
704         int totP;
705         
706         float mid = 0.0f;
707         short isOdd = 0;
708         
709         /* get lattice - we need the "edit lattice" from the lattice... confusing... */
710         lt = (Lattice *)obedit->data;
711         lt = lt->editlatt->latt;
712         
713         numU = lt->pntsu;
714         numV = lt->pntsv;
715         numW = lt->pntsw;
716         totP = numU * numV * numW;
717         
718         /* First Pass: determine midpoint - used for flipping center verts if there are odd number of points on axis */
719         switch (axis) {
720                 case LATTICE_FLIP_U:
721                         isOdd = numU & 1;
722                         break;
723                 case LATTICE_FLIP_V:
724                         isOdd = numV & 1;
725                         break;
726                 case LATTICE_FLIP_W:
727                         isOdd = numW & 1;
728                         break;
729                         
730                 default:
731                         printf("lattice_flip(): Unknown flipping axis (%u)\n", axis);
732                         return OPERATOR_CANCELLED;
733         }
734         
735         if (isOdd) {
736                 BPoint *bp;
737                 float avgInv = 1.0f / (float)totP;
738                 int i;
739                 
740                 /* midpoint calculation - assuming that u/v/w are axis-aligned */
741                 for (i = 0, bp = lt->def; i < totP; i++, bp++) {
742                         mid += bp->vec[axis] * avgInv;
743                 }
744         }
745         
746         /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
747         switch (axis) {
748                 case LATTICE_FLIP_U:
749                 {
750                         int u, v, w;
751                         
752                         /* v/w strips - front to back, top to bottom */
753                         for (w = 0; w < numW; w++) {
754                                 for (v = 0; v < numV; v++) {
755                                         /* swap coordinates of pairs of vertices on u */
756                                         for (u = 0; u < (numU / 2); u++) {
757                                                 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
758                                         }
759                                         
760                                         /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
761                                         if (isOdd) {
762                                                 u = (numU / 2);
763                                                 lattice_flip_point_value(lt, u, v, w, mid, axis);
764                                         }
765                                 }
766                         }
767                         break;
768                 }
769                 case LATTICE_FLIP_V:
770                 {
771                         int u, v, w;
772                         
773                         /* u/w strips - front to back, left to right */
774                         for (w = 0; w < numW; w++) {
775                                 for (u = 0; u < numU; u++) {
776                                         /* swap coordinates of pairs of vertices on v */
777                                         for (v = 0; v < (numV / 2); v++) {
778                                                 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
779                                         }
780                                         
781                                         /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
782                                         if (isOdd) {
783                                                 v = (numV / 2);
784                                                 lattice_flip_point_value(lt, u, v, w, mid, axis);
785                                         }
786                                 }
787                         }
788                         break;
789                 }
790                 case LATTICE_FLIP_W:
791                 {
792                         int u, v, w;
793                         
794                         for (v = 0; v < numV; v++) {
795                                 for (u = 0; u < numU; u++) {
796                                         /* swap coordinates of pairs of vertices on w */
797                                         for (w = 0; w < (numW / 2); w++) {
798                                                 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
799                                         }
800                                         
801                                         /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
802                                         if (isOdd) {
803                                                 w = (numW / 2);
804                                                 lattice_flip_point_value(lt, u, v, w, mid, axis);
805                                         }
806                                 }
807                         }
808                         break;
809                 }
810                 default: /* shouldn't happen, but just in case */
811                         break;
812         }
813         
814         /* updates */
815         DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
816         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
817         
818         return OPERATOR_FINISHED;
819 }
820
821 void LATTICE_OT_flip(wmOperatorType *ot)
822 {
823         static EnumPropertyItem flip_items[] = {
824                 {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
825                 {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
826                 {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
827                 {0, NULL, 0, NULL, NULL}};
828         
829         /* identifiers */
830         ot->name = "Flip (Distortion Free)";
831         ot->description = "Mirror all control points without inverting the lattice deform";
832         ot->idname = "LATTICE_OT_flip";
833         
834         /* api callbacks */
835         ot->poll = ED_operator_editlattice;
836         ot->invoke = WM_menu_invoke;
837         ot->exec = lattice_flip_exec;
838         
839         /* flags */
840         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
841         
842         /* properties */
843         ot->prop = RNA_def_enum(ot->srna, "axis", flip_items, LATTICE_FLIP_U, "Flip Axis", "Coordinates along this axis get flipped");
844 }
845
846 /****************************** Mouse Selection *************************/
847
848 static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2])
849 {
850         struct { BPoint *bp; float dist; int select; float mval_fl[2]; } *data = userData;
851         float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
852         
853         if ((bp->f1 & SELECT) && data->select)
854                 dist_test += 5.0f;
855
856         if (dist_test < data->dist) {
857                 data->dist = dist_test;
858
859                 data->bp = bp;
860         }
861 }
862
863 static BPoint *findnearestLattvert(ViewContext *vc, const int mval[2], int sel)
864 {
865         /* (sel == 1): selected gets a disadvantage */
866         /* in nurb and bezt or bp the nearest is written */
867         /* return 0 1 2: handlepunt */
868         struct { BPoint *bp; float dist; int select; float mval_fl[2]; } data = {NULL};
869
870         data.dist = ED_view3d_select_dist_px();
871         data.select = sel;
872         data.mval_fl[0] = mval[0];
873         data.mval_fl[1] = mval[1];
874
875         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
876         lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
877
878         return data.bp;
879 }
880
881 bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
882 {
883         ViewContext vc;
884         BPoint *bp = NULL;
885         Lattice *lt;
886
887         view3d_set_viewcontext(C, &vc);
888         lt = ((Lattice *)vc.obedit->data)->editlatt->latt;
889         bp = findnearestLattvert(&vc, mval, true);
890
891         if (bp) {
892                 if (extend) {
893                         bp->f1 |= SELECT;
894                 }
895                 else if (deselect) {
896                         bp->f1 &= ~SELECT;
897                 }
898                 else if (toggle) {
899                         bp->f1 ^= SELECT;  /* swap */
900                 }
901                 else {
902                         ED_lattice_flags_set(vc.obedit, 0);
903                         bp->f1 |= SELECT;
904                 }
905
906                 if (bp->f1 & SELECT) {
907                         lt->actbp = bp - lt->def;
908                 }
909                 else {
910                         lt->actbp = LT_ACTBP_NONE;
911                 }
912
913                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
914
915                 return true;
916         }
917
918         return false;
919 }
920
921 /******************************** Undo *************************/
922
923 typedef struct UndoLattice {
924         BPoint *def;
925         int pntsu, pntsv, pntsw, actbp;
926 } UndoLattice;
927
928 static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata))
929 {
930         UndoLattice *ult = (UndoLattice *)data;
931         EditLatt *editlatt = (EditLatt *)edata;
932         int a = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
933
934         memcpy(editlatt->latt->def, ult->def, a * sizeof(BPoint));
935         editlatt->latt->actbp = ult->actbp;
936 }
937
938 static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata))
939 {
940         UndoLattice *ult = MEM_callocN(sizeof(UndoLattice), "UndoLattice");
941         EditLatt *editlatt = (EditLatt *)edata;
942         
943         ult->def = MEM_dupallocN(editlatt->latt->def);
944         ult->pntsu = editlatt->latt->pntsu;
945         ult->pntsv = editlatt->latt->pntsv;
946         ult->pntsw = editlatt->latt->pntsw;
947         ult->actbp = editlatt->latt->actbp;
948         
949         return ult;
950 }
951
952 static void free_undoLatt(void *data)
953 {
954         UndoLattice *ult = (UndoLattice *)data;
955
956         if (ult->def) MEM_freeN(ult->def);
957         MEM_freeN(ult);
958 }
959
960 static int validate_undoLatt(void *data, void *edata)
961 {
962         UndoLattice *ult = (UndoLattice *)data;
963         EditLatt *editlatt = (EditLatt *)edata;
964
965         return (ult->pntsu == editlatt->latt->pntsu &&
966                 ult->pntsv == editlatt->latt->pntsv &&
967                 ult->pntsw == editlatt->latt->pntsw);
968 }
969
970 static void *get_editlatt(bContext *C)
971 {
972         Object *obedit = CTX_data_edit_object(C);
973
974         if (obedit && obedit->type == OB_LATTICE) {
975                 Lattice *lt = obedit->data;
976                 return lt->editlatt;
977         }
978
979         return NULL;
980 }
981
982 /* and this is all the undo system needs to know */
983 void undo_push_lattice(bContext *C, const char *name)
984 {
985         undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
986 }
987