svn merge -r41575:41602 ^/trunk/blender
[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= ob_get_keyblock(obedit);
96         if(actkey)
97                 key_to_latt(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) {
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 ^= 1;
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= "Select or Deselect 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                 resizelattice(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                 resizelattice(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, int x, int y)
306 {
307         struct { BPoint *bp; short dist, select; int mval[2]; } *data = userData;
308         float temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
309         
310         if((bp->f1 & SELECT)==data->select)
311                 temp += 5;
312
313         if(temp<data->dist) {
314                 data->dist = temp;
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; short dist, select; int mval[2]; } data = {NULL};
326
327         data.dist = 100;
328         data.select = sel;
329         data.mval[0]= mval[0];
330         data.mval[1]= mval[1];
331
332         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
333         lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data);
334
335         return data.bp;
336 }
337
338 int mouse_lattice(bContext *C, const int mval[2], int extend)
339 {
340         ViewContext vc;
341         BPoint *bp= NULL;
342
343         view3d_set_viewcontext(C, &vc);
344         bp= findnearestLattvert(&vc, mval, 1);
345
346         if(bp) {
347                 if(extend==0) {
348                         ED_setflagsLatt(vc.obedit, 0);
349                         bp->f1 |= SELECT;
350                 }
351                 else
352                         bp->f1 ^= SELECT; /* swap */
353
354                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
355
356                 return 1;
357         }
358
359         return 0;
360 }
361
362 /******************************** Undo *************************/
363
364 typedef struct UndoLattice {
365         BPoint *def;
366         int pntsu, pntsv, pntsw;
367 } UndoLattice;
368
369 static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata))
370 {
371         UndoLattice *ult= (UndoLattice*)data;
372         EditLatt *editlatt= (EditLatt *)edata;
373         int a= editlatt->latt->pntsu*editlatt->latt->pntsv*editlatt->latt->pntsw;
374
375         memcpy(editlatt->latt->def, ult->def, a*sizeof(BPoint));
376 }
377
378 static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata))
379 {
380         UndoLattice *ult= MEM_callocN(sizeof(UndoLattice), "UndoLattice");
381         EditLatt *editlatt= (EditLatt *)edata;
382         
383         ult->def= MEM_dupallocN(editlatt->latt->def);
384         ult->pntsu= editlatt->latt->pntsu;
385         ult->pntsv= editlatt->latt->pntsv;
386         ult->pntsw= editlatt->latt->pntsw;
387         
388         return ult;
389 }
390
391 static void free_undoLatt(void *data)
392 {
393         UndoLattice *ult= (UndoLattice*)data;
394
395         if(ult->def) MEM_freeN(ult->def);
396         MEM_freeN(ult);
397 }
398
399 static int validate_undoLatt(void *data, void *edata)
400 {
401         UndoLattice *ult= (UndoLattice*)data;
402         EditLatt *editlatt= (EditLatt *)edata;
403
404         return (ult->pntsu == editlatt->latt->pntsu &&
405                         ult->pntsv == editlatt->latt->pntsv &&
406                         ult->pntsw == editlatt->latt->pntsw);
407 }
408
409 static void *get_editlatt(bContext *C)
410 {
411         Object *obedit= CTX_data_edit_object(C);
412
413         if(obedit && obedit->type==OB_LATTICE) {
414                 Lattice *lt= obedit->data;
415                 return lt->editlatt;
416         }
417
418         return NULL;
419 }
420
421 /* and this is all the undo system needs to know */
422 void undo_push_lattice(bContext *C, const char *name)
423 {
424         undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
425 }
426