2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/object/object_lattice.c
35 #include "MEM_guardedalloc.h"
37 #include "BLI_listbase.h"
39 #include "BLI_utildefines.h"
41 #include "DNA_curve_types.h"
42 #include "DNA_key_types.h"
43 #include "DNA_lattice_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_scene_types.h"
48 #include "RNA_access.h"
50 #include "BKE_context.h"
51 #include "BKE_depsgraph.h"
53 #include "BKE_lattice.h"
56 #include "ED_lattice.h"
57 #include "ED_object.h"
58 #include "ED_screen.h"
59 #include "ED_view3d.h"
65 #include "object_intern.h"
67 /********************** Load/Make/Free ********************/
69 void free_editLatt(Object *ob)
71 Lattice *lt= ob->data;
74 Lattice *editlt= lt->editlatt->latt;
77 MEM_freeN(editlt->def);
79 free_dverts(editlt->dvert, editlt->pntsu*editlt->pntsv*editlt->pntsw);
82 MEM_freeN(lt->editlatt);
88 void make_editLatt(Object *obedit)
90 Lattice *lt= obedit->data;
93 free_editLatt(obedit);
95 actkey= ob_get_keyblock(obedit);
97 key_to_latt(actkey, lt);
99 lt->editlatt= MEM_callocN(sizeof(EditLatt), "editlatt");
100 lt->editlatt->latt= MEM_dupallocN(lt);
101 lt->editlatt->latt->def= MEM_dupallocN(lt->def);
104 int tot= lt->pntsu*lt->pntsv*lt->pntsw;
105 lt->editlatt->latt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
106 copy_dverts(lt->editlatt->latt->dvert, lt->dvert, tot);
109 if(lt->key) lt->editlatt->shapenr= obedit->shapenr;
112 void load_editLatt(Object *obedit)
114 Lattice *lt, *editlt;
121 editlt= lt->editlatt->latt;
123 if(lt->editlatt->shapenr) {
124 actkey= BLI_findlink(<->key->block, lt->editlatt->shapenr-1);
126 /* active key: vertices */
127 tot= editlt->pntsu*editlt->pntsv*editlt->pntsw;
129 if(actkey->data) MEM_freeN(actkey->data);
131 fp=actkey->data= MEM_callocN(lt->key->elemsize*tot, "actkey->data");
132 actkey->totelem= tot;
136 copy_v3_v3(fp, bp->vec);
144 lt->def= MEM_dupallocN(editlt->def);
146 lt->flag= editlt->flag;
148 lt->pntsu= editlt->pntsu;
149 lt->pntsv= editlt->pntsv;
150 lt->pntsw= editlt->pntsw;
152 lt->typeu= editlt->typeu;
153 lt->typev= editlt->typev;
154 lt->typew= editlt->typew;
158 free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
163 tot= lt->pntsu*lt->pntsv*lt->pntsw;
165 lt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
166 copy_dverts(lt->dvert, editlt->dvert, tot);
170 /************************** Operators *************************/
172 void ED_setflagsLatt(Object *obedit, int flag)
174 Lattice *lt= obedit->data;
178 bp= lt->editlatt->latt->def;
180 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
190 static int lattice_select_all_exec(bContext *C, wmOperator *op)
192 Object *obedit= CTX_data_edit_object(C);
193 Lattice *lt= obedit->data;
196 int action = RNA_enum_get(op->ptr, "action");
198 if (action == SEL_TOGGLE) {
201 bp= lt->editlatt->latt->def;
202 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
207 action = SEL_DESELECT;
217 ED_setflagsLatt(obedit, 1);
220 ED_setflagsLatt(obedit, 0);
223 bp= lt->editlatt->latt->def;
224 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
235 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
237 return OPERATOR_FINISHED;
240 void LATTICE_OT_select_all(wmOperatorType *ot)
243 ot->name= "Select or Deselect All";
244 ot->description= "Change selection of all UVW control points";
245 ot->idname= "LATTICE_OT_select_all";
248 ot->exec= lattice_select_all_exec;
249 ot->poll= ED_operator_editlattice;
252 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
254 WM_operator_properties_select_all(ot);
257 static int make_regular_poll(bContext *C)
261 if(ED_operator_editlattice(C)) return 1;
263 ob= CTX_data_active_object(C);
264 return (ob && ob->type==OB_LATTICE);
267 static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
269 Object *ob= CTX_data_edit_object(C);
274 resizelattice(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
277 ob= CTX_data_active_object(C);
279 resizelattice(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
282 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
283 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
285 return OPERATOR_FINISHED;
288 void LATTICE_OT_make_regular(wmOperatorType *ot)
291 ot->name= "Make Regular";
292 ot->description= "Set UVW control points a uniform distance apart";
293 ot->idname= "LATTICE_OT_make_regular";
296 ot->exec= make_regular_exec;
297 ot->poll= make_regular_poll;
300 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
303 /****************************** Mouse Selection *************************/
305 static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, int y)
307 struct { BPoint *bp; short dist, select; int mval[2]; } *data = userData;
308 float temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
310 if((bp->f1 & SELECT)==data->select)
313 if(temp<data->dist) {
320 static BPoint *findnearestLattvert(ViewContext *vc, const int mval[2], int sel)
322 /* sel==1: selected gets a disadvantage */
323 /* in nurb and bezt or bp the nearest is written */
324 /* return 0 1 2: handlepunt */
325 struct { BPoint *bp; short dist, select; int mval[2]; } data = {NULL};
329 data.mval[0]= mval[0];
330 data.mval[1]= mval[1];
332 ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
333 lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data);
338 int mouse_lattice(bContext *C, const int mval[2], int extend)
343 view3d_set_viewcontext(C, &vc);
344 bp= findnearestLattvert(&vc, mval, 1);
348 ED_setflagsLatt(vc.obedit, 0);
352 bp->f1 ^= SELECT; /* swap */
354 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
362 /******************************** Undo *************************/
364 typedef struct UndoLattice {
366 int pntsu, pntsv, pntsw;
369 static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata))
371 UndoLattice *ult= (UndoLattice*)data;
372 EditLatt *editlatt= (EditLatt *)edata;
373 int a= editlatt->latt->pntsu*editlatt->latt->pntsv*editlatt->latt->pntsw;
375 memcpy(editlatt->latt->def, ult->def, a*sizeof(BPoint));
378 static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata))
380 UndoLattice *ult= MEM_callocN(sizeof(UndoLattice), "UndoLattice");
381 EditLatt *editlatt= (EditLatt *)edata;
383 ult->def= MEM_dupallocN(editlatt->latt->def);
384 ult->pntsu= editlatt->latt->pntsu;
385 ult->pntsv= editlatt->latt->pntsv;
386 ult->pntsw= editlatt->latt->pntsw;
391 static void free_undoLatt(void *data)
393 UndoLattice *ult= (UndoLattice*)data;
395 if(ult->def) MEM_freeN(ult->def);
399 static int validate_undoLatt(void *data, void *edata)
401 UndoLattice *ult= (UndoLattice*)data;
402 EditLatt *editlatt= (EditLatt *)edata;
404 return (ult->pntsu == editlatt->latt->pntsu &&
405 ult->pntsv == editlatt->latt->pntsv &&
406 ult->pntsw == editlatt->latt->pntsw);
409 static void *get_editlatt(bContext *C)
411 Object *obedit= CTX_data_edit_object(C);
413 if(obedit && obedit->type==OB_LATTICE) {
414 Lattice *lt= obedit->data;
421 /* and this is all the undo system needs to know */
422 void undo_push_lattice(bContext *C, const char *name)
424 undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);