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