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