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