=bmesh= merge from trunk at r36529
[blender.git] / source / blender / editors / object / object_lattice.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/object/object_lattice.c
29  *  \ingroup edobj
30  */
31
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_listbase.h"
40 #include "BLI_utildefines.h"
41
42 #include "DNA_curve_types.h"
43 #include "DNA_key_types.h"
44 #include "DNA_lattice_types.h"
45 #include "DNA_meshdata_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_scene_types.h"
48
49 #include "RNA_access.h"
50
51 #include "BKE_context.h"
52 #include "BKE_depsgraph.h"
53 #include "BKE_key.h"
54 #include "BKE_lattice.h"
55 #include "BKE_mesh.h"
56
57 #include "ED_lattice.h"
58 #include "ED_object.h"
59 #include "ED_screen.h"
60 #include "ED_view3d.h"
61 #include "ED_util.h"
62
63 #include "WM_api.h"
64 #include "WM_types.h"
65
66 #include "object_intern.h"
67
68 /********************** Load/Make/Free ********************/
69
70 void free_editLatt(Object *ob)
71 {
72         Lattice *lt= ob->data;
73         
74         if(lt->editlatt) {
75                 Lattice *editlt= lt->editlatt->latt;
76
77                 if(editlt->def)
78                         MEM_freeN(editlt->def);
79                 if(editlt->dvert)
80                         free_dverts(editlt->dvert, editlt->pntsu*editlt->pntsv*editlt->pntsw);
81
82                 MEM_freeN(editlt);
83                 MEM_freeN(lt->editlatt);
84
85                 lt->editlatt= NULL;
86         }
87 }
88
89 void make_editLatt(Object *obedit)
90 {
91         Lattice *lt= obedit->data;
92         KeyBlock *actkey;
93
94         free_editLatt(obedit);
95
96         actkey= ob_get_keyblock(obedit);
97         if(actkey)
98                 key_to_latt(actkey, lt);
99
100         lt->editlatt= MEM_callocN(sizeof(EditLatt), "editlatt");
101         lt->editlatt->latt= MEM_dupallocN(lt);
102         lt->editlatt->latt->def= MEM_dupallocN(lt->def);
103
104         if(lt->dvert) {
105                 int tot= lt->pntsu*lt->pntsv*lt->pntsw;
106                 lt->editlatt->latt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
107                 copy_dverts(lt->editlatt->latt->dvert, lt->dvert, tot);
108         }
109
110         if(lt->key) lt->editlatt->shapenr= obedit->shapenr;
111 }
112
113 void load_editLatt(Object *obedit)
114 {
115         Lattice *lt, *editlt;
116         KeyBlock *actkey;
117         BPoint *bp;
118         float *fp;
119         int tot;
120
121         lt= obedit->data;
122         editlt= lt->editlatt->latt;
123
124         if(lt->editlatt->shapenr) {
125                 actkey= BLI_findlink(&lt->key->block, lt->editlatt->shapenr-1);
126
127                 /* active key: vertices */
128                 tot= editlt->pntsu*editlt->pntsv*editlt->pntsw;
129                 
130                 if(actkey->data) MEM_freeN(actkey->data);
131                 
132                 fp=actkey->data= MEM_callocN(lt->key->elemsize*tot, "actkey->data");
133                 actkey->totelem= tot;
134
135                 bp= editlt->def;
136                 while(tot--) {
137                         VECCOPY(fp, bp->vec);
138                         fp+= 3;
139                         bp++;
140                 }
141         }
142         else {
143                 MEM_freeN(lt->def);
144
145                 lt->def= MEM_dupallocN(editlt->def);
146
147                 lt->flag= editlt->flag;
148
149                 lt->pntsu= editlt->pntsu;
150                 lt->pntsv= editlt->pntsv;
151                 lt->pntsw= editlt->pntsw;
152                 
153                 lt->typeu= editlt->typeu;
154                 lt->typev= editlt->typev;
155                 lt->typew= editlt->typew;
156         }
157
158         if(lt->dvert) {
159                 free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
160                 lt->dvert= NULL;
161         }
162
163         if(editlt->dvert) {
164                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
165
166                 lt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
167                 copy_dverts(lt->dvert, editlt->dvert, tot);
168         }
169 }
170
171 /************************** Operators *************************/
172
173 void ED_setflagsLatt(Object *obedit, int flag)
174 {
175         Lattice *lt= obedit->data;
176         BPoint *bp;
177         int a;
178         
179         bp= lt->editlatt->latt->def;
180         
181         a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
182         
183         while(a--) {
184                 if(bp->hide==0) {
185                         bp->f1= flag;
186                 }
187                 bp++;
188         }
189 }
190
191 static int select_all_exec(bContext *C, wmOperator *op)
192 {
193         Object *obedit= CTX_data_edit_object(C);
194         Lattice *lt= obedit->data;
195         BPoint *bp;
196         int a;
197         int action = RNA_enum_get(op->ptr, "action");
198
199         if (action == SEL_TOGGLE) {
200                 action = SEL_SELECT;
201
202                 bp= lt->editlatt->latt->def;
203                 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
204
205                 while(a--) {
206                         if(bp->hide==0) {
207                                 if(bp->f1) {
208                                         action = SEL_DESELECT;
209                                         break;
210                                 }
211                         }
212                         bp++;
213                 }
214         }
215
216         switch (action) {
217         case SEL_SELECT:
218                 ED_setflagsLatt(obedit, 1);
219                 break;
220         case SEL_DESELECT:
221                 ED_setflagsLatt(obedit, 0);
222                 break;
223         case SEL_INVERT:
224                 bp= lt->editlatt->latt->def;
225                 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
226
227                 while(a--) {
228                         if(bp->hide==0) {
229                                 bp->f1 ^= 1;
230                         }
231                         bp++;
232                 }
233                 break;
234         }
235
236         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
237
238         return OPERATOR_FINISHED;
239 }
240
241 void LATTICE_OT_select_all(wmOperatorType *ot)
242 {
243         /* identifiers */
244         ot->name= "Select or Deselect All";
245         ot->description= "Change selection of all UVW control points";
246         ot->idname= "LATTICE_OT_select_all";
247         
248         /* api callbacks */
249         ot->exec= select_all_exec;
250         ot->poll= ED_operator_editlattice;
251         
252         /* flags */
253         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
254
255         WM_operator_properties_select_all(ot);
256 }
257
258 static int make_regular_poll(bContext *C)
259 {
260         Object *ob;
261
262         if(ED_operator_editlattice(C)) return 1;
263
264         ob= CTX_data_active_object(C);
265         return (ob && ob->type==OB_LATTICE);
266 }
267
268 static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
269 {
270         Object *ob= CTX_data_edit_object(C);
271         Lattice *lt;
272         
273         if(ob) {
274                 lt= ob->data;
275                 resizelattice(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
276         }
277         else {
278                 ob= CTX_data_active_object(C);
279                 lt= ob->data;
280                 resizelattice(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
281         }
282         
283         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
284         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
285
286         return OPERATOR_FINISHED;
287 }
288
289 void LATTICE_OT_make_regular(wmOperatorType *ot)
290 {
291         /* identifiers */
292         ot->name= "Make Regular";
293         ot->description= "Set UVW control points a uniform distance apart";
294         ot->idname= "LATTICE_OT_make_regular";
295         
296         /* api callbacks */
297         ot->exec= make_regular_exec;
298         ot->poll= make_regular_poll;
299         
300         /* flags */
301         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
302 }
303
304 /****************************** Mouse Selection *************************/
305
306 static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, int y)
307 {
308         struct { BPoint *bp; short dist, select, mval[2]; } *data = userData;
309         float temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
310         
311         if((bp->f1 & SELECT)==data->select)
312                 temp += 5;
313
314         if(temp<data->dist) {
315                 data->dist = temp;
316
317                 data->bp = bp;
318         }
319 }
320
321 static BPoint *findnearestLattvert(ViewContext *vc, const short mval[2], int sel)
322 {
323                 /* sel==1: selected gets a disadvantage */
324                 /* in nurb and bezt or bp the nearest is written */
325                 /* return 0 1 2: handlepunt */
326         struct { BPoint *bp; short dist, select, mval[2]; } data = {NULL};
327
328         data.dist = 100;
329         data.select = sel;
330         data.mval[0]= mval[0];
331         data.mval[1]= mval[1];
332
333         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
334         lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data);
335
336         return data.bp;
337 }
338
339 int mouse_lattice(bContext *C, const short mval[2], int extend)
340 {
341         ViewContext vc;
342         BPoint *bp= NULL;
343
344         view3d_set_viewcontext(C, &vc);
345         bp= findnearestLattvert(&vc, mval, 1);
346
347         if(bp) {
348                 if(extend==0) {
349                         ED_setflagsLatt(vc.obedit, 0);
350                         bp->f1 |= SELECT;
351                 }
352                 else
353                         bp->f1 ^= SELECT; /* swap */
354
355                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
356
357                 return 1;
358         }
359
360         return 0;
361 }
362
363 /******************************** Undo *************************/
364
365 typedef struct UndoLattice {
366         BPoint *def;
367         int pntsu, pntsv, pntsw;
368 } UndoLattice;
369
370 static void undoLatt_to_editLatt(void *data, void *edata, void *obdata)
371 {
372         UndoLattice *ult= (UndoLattice*)data;
373         EditLatt *editlatt= (EditLatt *)edata;
374         int a= editlatt->latt->pntsu*editlatt->latt->pntsv*editlatt->latt->pntsw;
375
376         memcpy(editlatt->latt->def, ult->def, a*sizeof(BPoint));
377 }
378
379 static void *editLatt_to_undoLatt(void *edata, void *obdata)
380 {
381         UndoLattice *ult= MEM_callocN(sizeof(UndoLattice), "UndoLattice");
382         EditLatt *editlatt= (EditLatt *)edata;
383         
384         ult->def= MEM_dupallocN(editlatt->latt->def);
385         ult->pntsu= editlatt->latt->pntsu;
386         ult->pntsv= editlatt->latt->pntsv;
387         ult->pntsw= editlatt->latt->pntsw;
388         
389         return ult;
390 }
391
392 static void free_undoLatt(void *data)
393 {
394         UndoLattice *ult= (UndoLattice*)data;
395
396         if(ult->def) MEM_freeN(ult->def);
397         MEM_freeN(ult);
398 }
399
400 static int validate_undoLatt(void *data, void *edata)
401 {
402         UndoLattice *ult= (UndoLattice*)data;
403         EditLatt *editlatt= (EditLatt *)edata;
404
405         return (ult->pntsu == editlatt->latt->pntsu &&
406                         ult->pntsv == editlatt->latt->pntsv &&
407                         ult->pntsw == editlatt->latt->pntsw);
408 }
409
410 static void *get_editlatt(bContext *C)
411 {
412         Object *obedit= CTX_data_edit_object(C);
413
414         if(obedit && obedit->type==OB_LATTICE) {
415                 Lattice *lt= obedit->data;
416                 return lt->editlatt;
417         }
418
419         return NULL;
420 }
421
422 /* and this is all the undo system needs to know */
423 void undo_push_lattice(bContext *C, const char *name)
424 {
425         undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
426 }
427