BLI_bitmap: rename macros
[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 free_editLatt(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 make_editLatt(Object *obedit)
95 {
96         Lattice *lt = obedit->data;
97         KeyBlock *actkey;
98
99         free_editLatt(obedit);
100
101         actkey = BKE_keyblock_from_object(obedit);
102         if (actkey)
103                 BKE_key_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 load_editLatt(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 /*************************** Transform Operator ************************/
178
179 void ED_lattice_transform(Lattice *lt, float mat[4][4])
180 {
181         BPoint *bp = lt->def;
182         int a = lt->pntsu * lt->pntsv * lt->pntsw;
183
184         while (a--) {
185                 mul_m4_v3(mat, bp->vec);
186                 bp++;
187         }
188
189         DAG_id_tag_update(&lt->id, 0);
190 }
191
192 static void bpoint_select_set(BPoint *bp, bool select)
193 {
194         if (select) {
195                 if (!bp->hide) {
196                         bp->f1 |= SELECT;
197                 }
198         }
199         else {
200                 bp->f1 &= ~SELECT;
201         }
202 }
203
204 /************************** Select Random Operator **********************/
205
206 static int lattice_select_random_exec(bContext *C, wmOperator *op)
207 {
208         Object *obedit = CTX_data_edit_object(C);
209         Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
210         const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
211         const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
212
213         int tot;
214         BPoint *bp;
215
216         tot = lt->pntsu * lt->pntsv * lt->pntsw;
217         bp = lt->def;
218         while (tot--) {
219                 if (!bp->hide) {
220                         if (BLI_frand() < randfac) {
221                                 bpoint_select_set(bp, select);
222                         }
223                 }
224                 bp++;
225         }
226
227         if (select == false) {
228                 lt->actbp = LT_ACTBP_NONE;
229         }
230
231         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
232
233         return OPERATOR_FINISHED;
234 }
235
236 void LATTICE_OT_select_random(wmOperatorType *ot)
237 {
238         /* identifiers */
239         ot->name = "Select Random";
240         ot->description = "Randomly select UVW control points";
241         ot->idname = "LATTICE_OT_select_random";
242
243         /* api callbacks */
244         ot->exec = lattice_select_random_exec;
245         ot->poll = ED_operator_editlattice;
246
247         /* flags */
248         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
249
250         /* props */
251         RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
252                                  "Percent", "Percentage of elements to select randomly", 0.f, 100.0f);
253         WM_operator_properties_select_action_simple(ot, SEL_SELECT);
254 }
255
256
257 /* -------------------------------------------------------------------- */
258 /* Select Mirror Operator */
259
260 static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
261 {
262         Object *obedit = CTX_data_edit_object(C);
263         Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
264         const bool extend = RNA_boolean_get(op->ptr, "extend");
265         const int axis = RNA_enum_get(op->ptr, "axis");
266         bool flip_uvw[3] = {false};
267         int tot, i;
268         BPoint *bp;
269         BLI_bitmap *selpoints;
270
271         tot = lt->pntsu * lt->pntsv * lt->pntsw;
272
273         flip_uvw[axis] = true;
274
275         if (!extend) {
276                 lt->actbp = LT_ACTBP_NONE;
277         }
278
279         /* store "original" selection */
280         selpoints = BLI_BITMAP_NEW(tot, __func__);
281         BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
282
283         /* actual (de)selection */
284         for (i = 0; i < tot; i++) {
285                 const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
286                 bp = &lt->def[i];
287                 if (!bp->hide) {
288                         if (BLI_BITMAP_TEST(selpoints, i_flip)) {
289                                 bp->f1 |= SELECT;
290                         }
291                         else {
292                                 if (!extend) {
293                                         bp->f1 &= ~SELECT;
294                                 }
295                         }
296                 }
297         }
298
299
300         MEM_freeN(selpoints);
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(ot->srna, "axis", object_axis_unsigned_items, 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_setflagsLatt(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_setflagsLatt(obedit, 1);
476                         break;
477                 case SEL_DESELECT:
478                         ED_setflagsLatt(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_setflagsLatt(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         DAG_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 (%d)\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         DAG_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 mouse_lattice(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_setflagsLatt(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