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