Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / lattice / editlattice_tools.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edlattice
22  */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "BLI_math.h"
27 #include "BLI_utildefines.h"
28
29 #include "DNA_curve_types.h"
30 #include "DNA_lattice_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_scene_types.h"
33
34 #include "RNA_access.h"
35 #include "RNA_define.h"
36
37 #include "BKE_context.h"
38 #include "BKE_lattice.h"
39 #include "BKE_layer.h"
40
41 #include "DEG_depsgraph.h"
42
43 #include "ED_screen.h"
44
45 #include "WM_api.h"
46 #include "WM_types.h"
47
48 #include "lattice_intern.h"
49
50 /** \} */
51
52 /* -------------------------------------------------------------------- */
53 /** \name Make Regular Operator
54  * \{ */
55
56 static bool make_regular_poll(bContext *C)
57 {
58   Object *ob;
59
60   if (ED_operator_editlattice(C)) {
61     return 1;
62   }
63
64   ob = CTX_data_active_object(C);
65   return (ob && ob->type == OB_LATTICE);
66 }
67
68 static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
69 {
70   ViewLayer *view_layer = CTX_data_view_layer(C);
71   View3D *v3d = CTX_wm_view3d(C);
72   const bool is_editmode = CTX_data_edit_object(C) != NULL;
73
74   if (is_editmode) {
75     uint objects_len;
76     Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
77         view_layer, CTX_wm_view3d(C), &objects_len);
78     for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
79       Object *ob = objects[ob_index];
80       Lattice *lt = ob->data;
81
82       if (lt->editlatt->latt == NULL) {
83         continue;
84       }
85
86       BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
87
88       DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
89       WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
90     }
91     MEM_freeN(objects);
92   }
93   else {
94     FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
95       if (ob->type != OB_LATTICE) {
96         continue;
97       }
98
99       Lattice *lt = ob->data;
100       BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
101
102       DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
103       WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
104     }
105     FOREACH_SELECTED_OBJECT_END;
106   }
107   return OPERATOR_FINISHED;
108 }
109
110 void LATTICE_OT_make_regular(wmOperatorType *ot)
111 {
112   /* identifiers */
113   ot->name = "Make Regular";
114   ot->description = "Set UVW control points a uniform distance apart";
115   ot->idname = "LATTICE_OT_make_regular";
116
117   /* api callbacks */
118   ot->exec = make_regular_exec;
119   ot->poll = make_regular_poll;
120
121   /* flags */
122   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
123 }
124
125 /** \} */
126
127 /* -------------------------------------------------------------------- */
128 /** \name Flip Verts Operator
129  * \{ */
130
131 /* flipping options */
132 typedef enum eLattice_FlipAxes {
133   LATTICE_FLIP_U = 0,
134   LATTICE_FLIP_V = 1,
135   LATTICE_FLIP_W = 2,
136 } eLattice_FlipAxes;
137
138 /**
139  * Flip midpoint value so that relative distances between midpoint and neighbor-pair is maintained.
140  * Assumes that uvw <=> xyz (i.e. axis-aligned index-axes with coordinate-axes).
141  * - Helper for #lattice_flip_exec()
142  */
143 static void lattice_flip_point_value(
144     Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
145 {
146   BPoint *bp;
147   float diff;
148
149   /* just the point in the middle (unpaired) */
150   bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
151
152   /* flip over axis */
153   diff = mid - bp->vec[axis];
154   bp->vec[axis] = mid + diff;
155 }
156
157 /**
158  * Swap pairs of lattice points along a specified axis.
159  * - Helper for #lattice_flip_exec()
160  */
161 static void lattice_swap_point_pairs(
162     Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
163 {
164   BPoint *bpA, *bpB;
165
166   int numU = lt->pntsu;
167   int numV = lt->pntsv;
168   int numW = lt->pntsw;
169
170   int u0 = u, u1 = u;
171   int v0 = v, v1 = v;
172   int w0 = w, w1 = w;
173
174   /* get pair index by just overriding the relevant pair-value
175    * - "-1" else buffer overflow
176    */
177   switch (axis) {
178     case LATTICE_FLIP_U:
179       u1 = numU - u - 1;
180       break;
181     case LATTICE_FLIP_V:
182       v1 = numV - v - 1;
183       break;
184     case LATTICE_FLIP_W:
185       w1 = numW - w - 1;
186       break;
187   }
188
189   /* get points to operate on */
190   bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
191   bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
192
193   /* Swap all coordinates, so that flipped coordinates belong to
194    * the indices on the correct side of the lattice.
195    *
196    *   Coords:  (-2 4) |0| (3 4)   --> (3 4) |0| (-2 4)
197    *   Indices:  (0,L)     (1,R)   --> (0,L)     (1,R)
198    */
199   swap_v3_v3(bpA->vec, bpB->vec);
200
201   /* However, we need to mirror the coordinate values on the axis we're dealing with,
202    * otherwise we'd have effectively only rotated the points around. If we don't do this,
203    * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
204    * such as flipped normals, etc.
205    *
206    *   Coords:  (3 4) |0| (-2 4)  --\
207    *                                 \-> (-3 4) |0| (2 4)
208    *   Indices: (0,L)     (1,R)   -->     (0,L)     (1,R)
209    */
210   lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
211   lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
212 }
213
214 static int lattice_flip_exec(bContext *C, wmOperator *op)
215 {
216   ViewLayer *view_layer = CTX_data_view_layer(C);
217   uint objects_len;
218   bool changed = false;
219   const eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
220
221   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
222       view_layer, CTX_wm_view3d(C), &objects_len);
223   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
224     Object *obedit = objects[ob_index];
225     Lattice *lt;
226
227     int numU, numV, numW;
228     int totP;
229
230     float mid = 0.0f;
231     short isOdd = 0;
232
233     /* get lattice - we need the "edit lattice" from the lattice... confusing... */
234     lt = (Lattice *)obedit->data;
235     lt = lt->editlatt->latt;
236
237     numU = lt->pntsu;
238     numV = lt->pntsv;
239     numW = lt->pntsw;
240     totP = numU * numV * numW;
241
242     /* First Pass: determine midpoint - used for flipping center verts if there
243      * are odd number of points on axis */
244     switch (axis) {
245       case LATTICE_FLIP_U:
246         isOdd = numU & 1;
247         break;
248       case LATTICE_FLIP_V:
249         isOdd = numV & 1;
250         break;
251       case LATTICE_FLIP_W:
252         isOdd = numW & 1;
253         break;
254
255       default:
256         printf("lattice_flip(): Unknown flipping axis (%u)\n", axis);
257         return OPERATOR_CANCELLED;
258     }
259
260     if (isOdd) {
261       BPoint *bp;
262       float avgInv = 1.0f / (float)totP;
263       int i;
264
265       /* midpoint calculation - assuming that u/v/w are axis-aligned */
266       for (i = 0, bp = lt->def; i < totP; i++, bp++) {
267         mid += bp->vec[axis] * avgInv;
268       }
269     }
270
271     /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
272     switch (axis) {
273       case LATTICE_FLIP_U: {
274         int u, v, w;
275
276         /* v/w strips - front to back, top to bottom */
277         for (w = 0; w < numW; w++) {
278           for (v = 0; v < numV; v++) {
279             /* swap coordinates of pairs of vertices on u */
280             for (u = 0; u < (numU / 2); u++) {
281               lattice_swap_point_pairs(lt, u, v, w, mid, axis);
282             }
283
284             /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
285             if (isOdd) {
286               u = (numU / 2);
287               lattice_flip_point_value(lt, u, v, w, mid, axis);
288             }
289           }
290         }
291         break;
292       }
293       case LATTICE_FLIP_V: {
294         int u, v, w;
295
296         /* u/w strips - front to back, left to right */
297         for (w = 0; w < numW; w++) {
298           for (u = 0; u < numU; u++) {
299             /* swap coordinates of pairs of vertices on v */
300             for (v = 0; v < (numV / 2); v++) {
301               lattice_swap_point_pairs(lt, u, v, w, mid, axis);
302             }
303
304             /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
305             if (isOdd) {
306               v = (numV / 2);
307               lattice_flip_point_value(lt, u, v, w, mid, axis);
308             }
309           }
310         }
311         break;
312       }
313       case LATTICE_FLIP_W: {
314         int u, v, w;
315
316         for (v = 0; v < numV; v++) {
317           for (u = 0; u < numU; u++) {
318             /* swap coordinates of pairs of vertices on w */
319             for (w = 0; w < (numW / 2); w++) {
320               lattice_swap_point_pairs(lt, u, v, w, mid, axis);
321             }
322
323             /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
324             if (isOdd) {
325               w = (numW / 2);
326               lattice_flip_point_value(lt, u, v, w, mid, axis);
327             }
328           }
329         }
330         break;
331       }
332       default: /* shouldn't happen, but just in case */
333         break;
334     }
335
336     /* updates */
337     DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
338     WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
339     changed = true;
340   }
341   MEM_freeN(objects);
342
343   return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
344 }
345
346 void LATTICE_OT_flip(wmOperatorType *ot)
347 {
348   static const EnumPropertyItem flip_items[] = {
349       {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
350       {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
351       {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
352       {0, NULL, 0, NULL, NULL},
353   };
354
355   /* identifiers */
356   ot->name = "Flip (Distortion Free)";
357   ot->description = "Mirror all control points without inverting the lattice deform";
358   ot->idname = "LATTICE_OT_flip";
359
360   /* api callbacks */
361   ot->poll = ED_operator_editlattice;
362   ot->invoke = WM_menu_invoke;
363   ot->exec = lattice_flip_exec;
364
365   /* flags */
366   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
367
368   /* properties */
369   ot->prop = RNA_def_enum(ot->srna,
370                           "axis",
371                           flip_items,
372                           LATTICE_FLIP_U,
373                           "Flip Axis",
374                           "Coordinates along this axis get flipped");
375 }
376
377 /** \} */