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