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