d8974ea677c921b0474fa6ca6ca52544cbae2cee
[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
41 #include "DNA_curve_types.h"
42 #include "DNA_key_types.h"
43 #include "DNA_lattice_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_scene_types.h"
47
48 #include "RNA_access.h"
49
50 #include "BKE_context.h"
51 #include "BKE_depsgraph.h"
52 #include "BKE_key.h"
53 #include "BKE_lattice.h"
54 #include "BKE_mesh.h"
55
56 #include "ED_lattice.h"
57 #include "ED_object.h"
58 #include "ED_screen.h"
59 #include "ED_view3d.h"
60 #include "ED_util.h"
61
62 #include "WM_api.h"
63 #include "WM_types.h"
64
65 #include "object_intern.h"
66
67 /********************** Load/Make/Free ********************/
68
69 void free_editLatt(Object *ob)
70 {
71         Lattice *lt = ob->data;
72         
73         if (lt->editlatt) {
74                 Lattice *editlt = lt->editlatt->latt;
75
76                 if (editlt->def)
77                         MEM_freeN(editlt->def);
78                 if (editlt->dvert)
79                         free_dverts(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
80
81                 MEM_freeN(editlt);
82                 MEM_freeN(lt->editlatt);
83
84                 lt->editlatt = NULL;
85         }
86 }
87
88 void make_editLatt(Object *obedit)
89 {
90         Lattice *lt = obedit->data;
91         KeyBlock *actkey;
92
93         free_editLatt(obedit);
94
95         actkey = BKE_keyblock_from_object(obedit);
96         if (actkey)
97                 BKE_key_convert_to_lattice(actkey, lt);
98
99         lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt");
100         lt->editlatt->latt = MEM_dupallocN(lt);
101         lt->editlatt->latt->def = MEM_dupallocN(lt->def);
102
103         if (lt->dvert) {
104                 int tot = lt->pntsu * lt->pntsv * lt->pntsw;
105                 lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
106                 copy_dverts(lt->editlatt->latt->dvert, lt->dvert, tot);
107         }
108
109         if (lt->key) lt->editlatt->shapenr = obedit->shapenr;
110 }
111
112 void load_editLatt(Object *obedit)
113 {
114         Lattice *lt, *editlt;
115         KeyBlock *actkey;
116         BPoint *bp;
117         float *fp;
118         int tot;
119
120         lt = obedit->data;
121         editlt = lt->editlatt->latt;
122
123         if (lt->editlatt->shapenr) {
124                 actkey = BLI_findlink(&lt->key->block, lt->editlatt->shapenr - 1);
125
126                 /* active key: vertices */
127                 tot = editlt->pntsu * editlt->pntsv * editlt->pntsw;
128                 
129                 if (actkey->data) MEM_freeN(actkey->data);
130                 
131                 fp = actkey->data = MEM_callocN(lt->key->elemsize * tot, "actkey->data");
132                 actkey->totelem = tot;
133
134                 bp = editlt->def;
135                 while (tot--) {
136                         copy_v3_v3(fp, bp->vec);
137                         fp += 3;
138                         bp++;
139                 }
140         }
141         else {
142                 MEM_freeN(lt->def);
143
144                 lt->def = MEM_dupallocN(editlt->def);
145
146                 lt->flag = editlt->flag;
147
148                 lt->pntsu = editlt->pntsu;
149                 lt->pntsv = editlt->pntsv;
150                 lt->pntsw = editlt->pntsw;
151                 
152                 lt->typeu = editlt->typeu;
153                 lt->typev = editlt->typev;
154                 lt->typew = editlt->typew;
155         }
156
157         if (lt->dvert) {
158                 free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
159                 lt->dvert = NULL;
160         }
161
162         if (editlt->dvert) {
163                 tot = lt->pntsu * lt->pntsv * lt->pntsw;
164
165                 lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
166                 copy_dverts(lt->dvert, editlt->dvert, tot);
167         }
168 }
169
170 /************************** Operators *************************/
171
172 void ED_setflagsLatt(Object *obedit, int flag)
173 {
174         Lattice *lt = obedit->data;
175         BPoint *bp;
176         int a;
177         
178         bp = lt->editlatt->latt->def;
179         
180         a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
181         
182         while (a--) {
183                 if (bp->hide == 0) {
184                         bp->f1 = flag;
185                 }
186                 bp++;
187         }
188 }
189
190 static int lattice_select_all_exec(bContext *C, wmOperator *op)
191 {
192         Object *obedit = CTX_data_edit_object(C);
193         Lattice *lt = obedit->data;
194         BPoint *bp;
195         int a;
196         int action = RNA_enum_get(op->ptr, "action");
197
198         if (action == SEL_TOGGLE) {
199                 action = SEL_SELECT;
200
201                 bp = lt->editlatt->latt->def;
202                 a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
203
204                 while (a--) {
205                         if (bp->hide == 0) {
206                                 if (bp->f1 & SELECT) {
207                                         action = SEL_DESELECT;
208                                         break;
209                                 }
210                         }
211                         bp++;
212                 }
213         }
214
215         switch (action) {
216                 case SEL_SELECT:
217                         ED_setflagsLatt(obedit, 1);
218                         break;
219                 case SEL_DESELECT:
220                         ED_setflagsLatt(obedit, 0);
221                         break;
222                 case SEL_INVERT:
223                         bp = lt->editlatt->latt->def;
224                         a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
225
226                         while (a--) {
227                                 if (bp->hide == 0) {
228                                         bp->f1 ^= SELECT;
229                                 }
230                                 bp++;
231                         }
232                         break;
233         }
234
235         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
236
237         return OPERATOR_FINISHED;
238 }
239
240 void LATTICE_OT_select_all(wmOperatorType *ot)
241 {
242         /* identifiers */
243         ot->name = "(De)select All";
244         ot->description = "Change selection of all UVW control points";
245         ot->idname = "LATTICE_OT_select_all";
246         
247         /* api callbacks */
248         ot->exec = lattice_select_all_exec;
249         ot->poll = ED_operator_editlattice;
250         
251         /* flags */
252         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
253
254         WM_operator_properties_select_all(ot);
255 }
256
257 static int make_regular_poll(bContext *C)
258 {
259         Object *ob;
260
261         if (ED_operator_editlattice(C)) return 1;
262
263         ob = CTX_data_active_object(C);
264         return (ob && ob->type == OB_LATTICE);
265 }
266
267 static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
268 {
269         Object *ob = CTX_data_edit_object(C);
270         Lattice *lt;
271         
272         if (ob) {
273                 lt = ob->data;
274                 BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
275         }
276         else {
277                 ob = CTX_data_active_object(C);
278                 lt = ob->data;
279                 BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
280         }
281         
282         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
283         WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
284
285         return OPERATOR_FINISHED;
286 }
287
288 void LATTICE_OT_make_regular(wmOperatorType *ot)
289 {
290         /* identifiers */
291         ot->name = "Make Regular";
292         ot->description = "Set UVW control points a uniform distance apart";
293         ot->idname = "LATTICE_OT_make_regular";
294         
295         /* api callbacks */
296         ot->exec = make_regular_exec;
297         ot->poll = make_regular_poll;
298         
299         /* flags */
300         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
301 }
302
303 /****************************** Mouse Selection *************************/
304
305 static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2])
306 {
307         struct { BPoint *bp; float dist; int select; float mval_fl[2]; } *data = userData;
308         float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
309         
310         if ((bp->f1 & SELECT) && data->select)
311                 dist_test += 5.0f;
312
313         if (dist_test < data->dist) {
314                 data->dist = dist_test;
315
316                 data->bp = bp;
317         }
318 }
319
320 static BPoint *findnearestLattvert(ViewContext *vc, const int mval[2], int sel)
321 {
322         /* sel==1: selected gets a disadvantage */
323         /* in nurb and bezt or bp the nearest is written */
324         /* return 0 1 2: handlepunt */
325         struct { BPoint *bp; float dist; int select; float mval_fl[2]; } data = {NULL};
326
327         data.dist = 100;
328         data.select = sel;
329         data.mval_fl[0] = mval[0];
330         data.mval_fl[1] = mval[1];
331
332         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
333         lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
334
335         return data.bp;
336 }
337
338 int mouse_lattice(bContext *C, const int mval[2], int extend, int deselect, int toggle)
339 {
340         ViewContext vc;
341         BPoint *bp = NULL;
342
343         view3d_set_viewcontext(C, &vc);
344         bp = findnearestLattvert(&vc, mval, TRUE);
345
346         if (bp) {
347                 if (extend) {
348                         bp->f1 |= SELECT;
349                 }
350                 else if (deselect) {
351                         bp->f1 &= ~SELECT;
352                 }
353                 else if (toggle) {
354                         bp->f1 ^= SELECT;  /* swap */
355                 }
356                 else {
357                         ED_setflagsLatt(vc.obedit, 0);
358                         bp->f1 |= SELECT;
359                 }
360
361                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
362
363                 return 1;
364         }
365
366         return 0;
367 }
368
369 /******************************** Undo *************************/
370
371 typedef struct UndoLattice {
372         BPoint *def;
373         int pntsu, pntsv, pntsw;
374 } UndoLattice;
375
376 static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata))
377 {
378         UndoLattice *ult = (UndoLattice *)data;
379         EditLatt *editlatt = (EditLatt *)edata;
380         int a = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
381
382         memcpy(editlatt->latt->def, ult->def, a * sizeof(BPoint));
383 }
384
385 static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata))
386 {
387         UndoLattice *ult = MEM_callocN(sizeof(UndoLattice), "UndoLattice");
388         EditLatt *editlatt = (EditLatt *)edata;
389         
390         ult->def = MEM_dupallocN(editlatt->latt->def);
391         ult->pntsu = editlatt->latt->pntsu;
392         ult->pntsv = editlatt->latt->pntsv;
393         ult->pntsw = editlatt->latt->pntsw;
394         
395         return ult;
396 }
397
398 static void free_undoLatt(void *data)
399 {
400         UndoLattice *ult = (UndoLattice *)data;
401
402         if (ult->def) MEM_freeN(ult->def);
403         MEM_freeN(ult);
404 }
405
406 static int validate_undoLatt(void *data, void *edata)
407 {
408         UndoLattice *ult = (UndoLattice *)data;
409         EditLatt *editlatt = (EditLatt *)edata;
410
411         return (ult->pntsu == editlatt->latt->pntsu &&
412                 ult->pntsv == editlatt->latt->pntsv &&
413                 ult->pntsw == editlatt->latt->pntsw);
414 }
415
416 static void *get_editlatt(bContext *C)
417 {
418         Object *obedit = CTX_data_edit_object(C);
419
420         if (obedit && obedit->type == OB_LATTICE) {
421                 Lattice *lt = obedit->data;
422                 return lt->editlatt;
423         }
424
425         return NULL;
426 }
427
428 /* and this is all the undo system needs to know */
429 void undo_push_lattice(bContext *C, const char *name)
430 {
431         undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
432 }
433