Merge with -r 22620:23107.
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #include <stdlib.h>
29 #include <string.h>
30 #include <math.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_curve_types.h"
35 #include "DNA_key_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_scene_types.h"
40
41 #include "BKE_context.h"
42 #include "BKE_depsgraph.h"
43 #include "BKE_key.h"
44 #include "BKE_lattice.h"
45 #include "BKE_mesh.h"
46 #include "BKE_utildefines.h"
47
48 #include "ED_object.h"
49 #include "ED_screen.h"
50 #include "ED_view3d.h"
51 #include "ED_util.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "object_intern.h"
57
58 /********************** Load/Make/Free ********************/
59
60 void free_editLatt(Object *ob)
61 {
62         Lattice *lt= ob->data;
63         
64         if(lt->editlatt) {
65                 if(lt->editlatt->def)
66                         MEM_freeN(lt->editlatt->def);
67                 if(lt->editlatt->dvert) 
68                         free_dverts(lt->editlatt->dvert, lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw);
69                 
70                 MEM_freeN(lt->editlatt);
71                 lt->editlatt= NULL;
72         }
73 }
74
75 void make_editLatt(Object *obedit)
76 {
77         Lattice *lt= obedit->data;
78         KeyBlock *actkey;
79         
80         free_editLatt(obedit);
81         
82         lt= obedit->data;
83
84         actkey= ob_get_keyblock(obedit);
85         if(actkey)
86                 key_to_latt(actkey, lt);
87
88         lt->editlatt= MEM_dupallocN(lt);
89         lt->editlatt->def= MEM_dupallocN(lt->def);
90         
91         if(lt->dvert) {
92                 int tot= lt->pntsu*lt->pntsv*lt->pntsw;
93                 lt->editlatt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
94                 copy_dverts(lt->editlatt->dvert, lt->dvert, tot);
95         }
96 }
97
98 void load_editLatt(Object *obedit)
99 {
100         Lattice *lt;
101         KeyBlock *actkey;
102         BPoint *bp;
103         float *fp;
104         int tot;
105         
106         lt= obedit->data;
107         
108         actkey= ob_get_keyblock(obedit);
109
110         if(actkey) {
111                 /* active key: vertices */
112                 tot= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
113                 
114                 if(actkey->data) MEM_freeN(actkey->data);
115                 
116                 fp=actkey->data= MEM_callocN(lt->key->elemsize*tot, "actkey->data");
117                 actkey->totelem= tot;
118         
119                 bp= lt->editlatt->def;
120                 while(tot--) {
121                         VECCOPY(fp, bp->vec);
122                         fp+= 3;
123                         bp++;
124                 }
125         }
126         else {
127                 MEM_freeN(lt->def);
128         
129                 lt->def= MEM_dupallocN(lt->editlatt->def);
130
131                 lt->flag= lt->editlatt->flag;
132
133                 lt->pntsu= lt->editlatt->pntsu;
134                 lt->pntsv= lt->editlatt->pntsv;
135                 lt->pntsw= lt->editlatt->pntsw;
136                 
137                 lt->typeu= lt->editlatt->typeu;
138                 lt->typev= lt->editlatt->typev;
139                 lt->typew= lt->editlatt->typew;
140         }
141         
142         if(lt->dvert) {
143                 free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
144                 lt->dvert= NULL;
145         }
146         
147         if(lt->editlatt->dvert) {
148                 int tot= lt->pntsu*lt->pntsv*lt->pntsw;
149                 
150                 lt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
151                 copy_dverts(lt->dvert, lt->editlatt->dvert, tot);
152         }
153 }
154
155 /************************** Operators *************************/
156
157 static void setflagsLatt(Object *obedit, int flag)
158 {
159         Lattice *lt= obedit->data;
160         BPoint *bp;
161         int a;
162         
163         bp= lt->editlatt->def;
164         
165         a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
166         
167         while(a--) {
168                 if(bp->hide==0) {
169                         bp->f1= flag;
170                 }
171                 bp++;
172         }
173 }
174
175 int de_select_all_exec(bContext *C, wmOperator *op)
176 {
177         Object *obedit= CTX_data_edit_object(C);
178         Lattice *lt= obedit->data;
179         BPoint *bp;
180         int a, deselect= 0;
181         
182         bp= lt->editlatt->def;
183         a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
184         
185         while(a--) {
186                 if(bp->hide==0) {
187                         if(bp->f1) {
188                                 deselect= 1;
189                                 break;
190                         }
191                 }
192                 bp++;
193         }
194
195         if(deselect)
196                 setflagsLatt(obedit, 0);
197         else
198                 setflagsLatt(obedit, 1);
199         
200         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
201
202         return OPERATOR_FINISHED;
203 }
204
205 void LATTICE_OT_select_all_toggle(wmOperatorType *ot)
206 {
207         /* identifiers */
208         ot->name= "Select or Deselect All";
209         ot->idname= "LATTICE_OT_select_all_toggle";
210         
211         /* api callbacks */
212         ot->exec= de_select_all_exec;
213         ot->poll= ED_operator_editlattice;
214         
215         /* flags */
216         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
217 }
218
219 int make_regular_poll(bContext *C)
220 {
221         Object *ob;
222
223         if(ED_operator_editlattice(C)) return 1;
224
225         ob= CTX_data_active_object(C);
226         return (ob && ob->type==OB_LATTICE);
227 }
228
229 int make_regular_exec(bContext *C, wmOperator *op)
230 {
231         Object *ob= CTX_data_edit_object(C);
232         Lattice *lt;
233         
234         if(ob) {
235                 lt= ob->data;
236                 resizelattice(lt->editlatt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
237         }
238         else {
239                 ob= CTX_data_active_object(C);
240                 lt= ob->data;
241                 resizelattice(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
242         }
243         
244         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
245         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
246
247         return OPERATOR_FINISHED;
248 }
249
250 void LATTICE_OT_make_regular(wmOperatorType *ot)
251 {
252         /* identifiers */
253         ot->name= "Make Regular";
254         ot->idname= "LATTICE_OT_make_regular";
255         
256         /* api callbacks */
257         ot->exec= make_regular_exec;
258         ot->poll= make_regular_poll;
259         
260         /* flags */
261         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
262 }
263
264 /****************************** Mouse Selection *************************/
265
266 static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, int y)
267 {
268         struct { BPoint *bp; short dist, select, mval[2]; } *data = userData;
269         float temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
270         
271         if((bp->f1 & SELECT)==data->select)
272                 temp += 5;
273
274         if(temp<data->dist) {
275                 data->dist = temp;
276
277                 data->bp = bp;
278         }
279 }
280
281 static BPoint *findnearestLattvert(ViewContext *vc, short mval[2], int sel)
282 {
283                 /* sel==1: selected gets a disadvantage */
284                 /* in nurb and bezt or bp the nearest is written */
285                 /* return 0 1 2: handlepunt */
286         struct { BPoint *bp; short dist, select, mval[2]; } data = {0};
287
288         data.dist = 100;
289         data.select = sel;
290         data.mval[0]= mval[0];
291         data.mval[1]= mval[1];
292
293         lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data);
294
295         return data.bp;
296 }
297
298 void mouse_lattice(bContext *C, short mval[2], int extend)
299 {
300         ViewContext vc;
301         BPoint *bp= NULL;
302
303         view3d_set_viewcontext(C, &vc);
304         bp= findnearestLattvert(&vc, mval, 1);
305
306         if(bp) {
307                 if(extend==0) {
308                         setflagsLatt(vc.obedit, 0);
309                         bp->f1 |= SELECT;
310                 }
311                 else
312                         bp->f1 ^= SELECT; /* swap */
313
314                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
315         }
316 }
317
318 /******************************** Undo *************************/
319
320 typedef struct UndoLattice {
321         BPoint *def;
322         int pntsu, pntsv, pntsw;
323 } UndoLattice;
324
325 static void undoLatt_to_editLatt(void *data, void *edata)
326 {
327         UndoLattice *ult= (UndoLattice*)data;
328         Lattice *editlatt= (Lattice *)edata;
329         int a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
330
331         memcpy(editlatt->def, ult->def, a*sizeof(BPoint));
332 }
333
334 static void *editLatt_to_undoLatt(void *edata)
335 {
336         UndoLattice *ult= MEM_callocN(sizeof(UndoLattice), "UndoLattice");
337         Lattice *editlatt= (Lattice *)edata;
338         
339         ult->def= MEM_dupallocN(editlatt->def);
340         ult->pntsu= editlatt->pntsu;
341         ult->pntsv= editlatt->pntsv;
342         ult->pntsw= editlatt->pntsw;
343         
344         return ult;
345 }
346
347 static void free_undoLatt(void *data)
348 {
349         UndoLattice *ult= (UndoLattice*)data;
350
351         if(ult->def) MEM_freeN(ult->def);
352         MEM_freeN(ult);
353 }
354
355 static int validate_undoLatt(void *data, void *edata)
356 {
357         UndoLattice *ult= (UndoLattice*)data;
358         Lattice *editlatt= (Lattice *)edata;
359
360         return (ult->pntsu == editlatt->pntsu &&
361                 ult->pntsv == editlatt->pntsv &&
362                 ult->pntsw == editlatt->pntsw);
363 }
364
365 static void *get_editlatt(bContext *C)
366 {
367         Object *obedit= CTX_data_edit_object(C);
368
369         if(obedit && obedit->type==OB_LATTICE) {
370                 Lattice *lt= obedit->data;
371                 return lt->editlatt;
372         }
373
374         return NULL;
375 }
376
377 /* and this is all the undo system needs to know */
378 void undo_push_lattice(bContext *C, char *name)
379 {
380         undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
381 }
382