Blender  V2.59
object_lattice.c
Go to the documentation of this file.
00001 /*
00002  * $Id: object_lattice.c 36644 2011-05-12 16:47:36Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * Contributor(s): Blender Foundation
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <math.h>
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "BLI_listbase.h"
00040 #include "BLI_utildefines.h"
00041 
00042 #include "DNA_curve_types.h"
00043 #include "DNA_key_types.h"
00044 #include "DNA_lattice_types.h"
00045 #include "DNA_meshdata_types.h"
00046 #include "DNA_object_types.h"
00047 #include "DNA_scene_types.h"
00048 
00049 #include "RNA_access.h"
00050 
00051 #include "BKE_context.h"
00052 #include "BKE_depsgraph.h"
00053 #include "BKE_key.h"
00054 #include "BKE_lattice.h"
00055 #include "BKE_mesh.h"
00056 
00057 #include "ED_lattice.h"
00058 #include "ED_object.h"
00059 #include "ED_screen.h"
00060 #include "ED_view3d.h"
00061 #include "ED_util.h"
00062 
00063 #include "WM_api.h"
00064 #include "WM_types.h"
00065 
00066 #include "object_intern.h"
00067 
00068 /********************** Load/Make/Free ********************/
00069 
00070 void free_editLatt(Object *ob)
00071 {
00072         Lattice *lt= ob->data;
00073         
00074         if(lt->editlatt) {
00075                 Lattice *editlt= lt->editlatt->latt;
00076 
00077                 if(editlt->def)
00078                         MEM_freeN(editlt->def);
00079                 if(editlt->dvert)
00080                         free_dverts(editlt->dvert, editlt->pntsu*editlt->pntsv*editlt->pntsw);
00081 
00082                 MEM_freeN(editlt);
00083                 MEM_freeN(lt->editlatt);
00084 
00085                 lt->editlatt= NULL;
00086         }
00087 }
00088 
00089 void make_editLatt(Object *obedit)
00090 {
00091         Lattice *lt= obedit->data;
00092         KeyBlock *actkey;
00093 
00094         free_editLatt(obedit);
00095 
00096         actkey= ob_get_keyblock(obedit);
00097         if(actkey)
00098                 key_to_latt(actkey, lt);
00099 
00100         lt->editlatt= MEM_callocN(sizeof(EditLatt), "editlatt");
00101         lt->editlatt->latt= MEM_dupallocN(lt);
00102         lt->editlatt->latt->def= MEM_dupallocN(lt->def);
00103 
00104         if(lt->dvert) {
00105                 int tot= lt->pntsu*lt->pntsv*lt->pntsw;
00106                 lt->editlatt->latt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
00107                 copy_dverts(lt->editlatt->latt->dvert, lt->dvert, tot);
00108         }
00109 
00110         if(lt->key) lt->editlatt->shapenr= obedit->shapenr;
00111 }
00112 
00113 void load_editLatt(Object *obedit)
00114 {
00115         Lattice *lt, *editlt;
00116         KeyBlock *actkey;
00117         BPoint *bp;
00118         float *fp;
00119         int tot;
00120 
00121         lt= obedit->data;
00122         editlt= lt->editlatt->latt;
00123 
00124         if(lt->editlatt->shapenr) {
00125                 actkey= BLI_findlink(&lt->key->block, lt->editlatt->shapenr-1);
00126 
00127                 /* active key: vertices */
00128                 tot= editlt->pntsu*editlt->pntsv*editlt->pntsw;
00129                 
00130                 if(actkey->data) MEM_freeN(actkey->data);
00131                 
00132                 fp=actkey->data= MEM_callocN(lt->key->elemsize*tot, "actkey->data");
00133                 actkey->totelem= tot;
00134 
00135                 bp= editlt->def;
00136                 while(tot--) {
00137                         VECCOPY(fp, bp->vec);
00138                         fp+= 3;
00139                         bp++;
00140                 }
00141         }
00142         else {
00143                 MEM_freeN(lt->def);
00144 
00145                 lt->def= MEM_dupallocN(editlt->def);
00146 
00147                 lt->flag= editlt->flag;
00148 
00149                 lt->pntsu= editlt->pntsu;
00150                 lt->pntsv= editlt->pntsv;
00151                 lt->pntsw= editlt->pntsw;
00152                 
00153                 lt->typeu= editlt->typeu;
00154                 lt->typev= editlt->typev;
00155                 lt->typew= editlt->typew;
00156         }
00157 
00158         if(lt->dvert) {
00159                 free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
00160                 lt->dvert= NULL;
00161         }
00162 
00163         if(editlt->dvert) {
00164                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
00165 
00166                 lt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
00167                 copy_dverts(lt->dvert, editlt->dvert, tot);
00168         }
00169 }
00170 
00171 /************************** Operators *************************/
00172 
00173 void ED_setflagsLatt(Object *obedit, int flag)
00174 {
00175         Lattice *lt= obedit->data;
00176         BPoint *bp;
00177         int a;
00178         
00179         bp= lt->editlatt->latt->def;
00180         
00181         a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
00182         
00183         while(a--) {
00184                 if(bp->hide==0) {
00185                         bp->f1= flag;
00186                 }
00187                 bp++;
00188         }
00189 }
00190 
00191 static int select_all_exec(bContext *C, wmOperator *op)
00192 {
00193         Object *obedit= CTX_data_edit_object(C);
00194         Lattice *lt= obedit->data;
00195         BPoint *bp;
00196         int a;
00197         int action = RNA_enum_get(op->ptr, "action");
00198 
00199         if (action == SEL_TOGGLE) {
00200                 action = SEL_SELECT;
00201 
00202                 bp= lt->editlatt->latt->def;
00203                 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
00204 
00205                 while(a--) {
00206                         if(bp->hide==0) {
00207                                 if(bp->f1) {
00208                                         action = SEL_DESELECT;
00209                                         break;
00210                                 }
00211                         }
00212                         bp++;
00213                 }
00214         }
00215 
00216         switch (action) {
00217         case SEL_SELECT:
00218                 ED_setflagsLatt(obedit, 1);
00219                 break;
00220         case SEL_DESELECT:
00221                 ED_setflagsLatt(obedit, 0);
00222                 break;
00223         case SEL_INVERT:
00224                 bp= lt->editlatt->latt->def;
00225                 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
00226 
00227                 while(a--) {
00228                         if(bp->hide==0) {
00229                                 bp->f1 ^= 1;
00230                         }
00231                         bp++;
00232                 }
00233                 break;
00234         }
00235 
00236         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
00237 
00238         return OPERATOR_FINISHED;
00239 }
00240 
00241 void LATTICE_OT_select_all(wmOperatorType *ot)
00242 {
00243         /* identifiers */
00244         ot->name= "Select or Deselect All";
00245         ot->description= "Change selection of all UVW control points";
00246         ot->idname= "LATTICE_OT_select_all";
00247         
00248         /* api callbacks */
00249         ot->exec= select_all_exec;
00250         ot->poll= ED_operator_editlattice;
00251         
00252         /* flags */
00253         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00254 
00255         WM_operator_properties_select_all(ot);
00256 }
00257 
00258 static int make_regular_poll(bContext *C)
00259 {
00260         Object *ob;
00261 
00262         if(ED_operator_editlattice(C)) return 1;
00263 
00264         ob= CTX_data_active_object(C);
00265         return (ob && ob->type==OB_LATTICE);
00266 }
00267 
00268 static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
00269 {
00270         Object *ob= CTX_data_edit_object(C);
00271         Lattice *lt;
00272         
00273         if(ob) {
00274                 lt= ob->data;
00275                 resizelattice(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
00276         }
00277         else {
00278                 ob= CTX_data_active_object(C);
00279                 lt= ob->data;
00280                 resizelattice(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
00281         }
00282         
00283         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00284         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
00285 
00286         return OPERATOR_FINISHED;
00287 }
00288 
00289 void LATTICE_OT_make_regular(wmOperatorType *ot)
00290 {
00291         /* identifiers */
00292         ot->name= "Make Regular";
00293         ot->description= "Set UVW control points a uniform distance apart";
00294         ot->idname= "LATTICE_OT_make_regular";
00295         
00296         /* api callbacks */
00297         ot->exec= make_regular_exec;
00298         ot->poll= make_regular_poll;
00299         
00300         /* flags */
00301         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00302 }
00303 
00304 /****************************** Mouse Selection *************************/
00305 
00306 static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, int y)
00307 {
00308         struct { BPoint *bp; short dist, select; int mval[2]; } *data = userData;
00309         float temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
00310         
00311         if((bp->f1 & SELECT)==data->select)
00312                 temp += 5;
00313 
00314         if(temp<data->dist) {
00315                 data->dist = temp;
00316 
00317                 data->bp = bp;
00318         }
00319 }
00320 
00321 static BPoint *findnearestLattvert(ViewContext *vc, const int mval[2], int sel)
00322 {
00323                 /* sel==1: selected gets a disadvantage */
00324                 /* in nurb and bezt or bp the nearest is written */
00325                 /* return 0 1 2: handlepunt */
00326         struct { BPoint *bp; short dist, select; int mval[2]; } data = {NULL};
00327 
00328         data.dist = 100;
00329         data.select = sel;
00330         data.mval[0]= mval[0];
00331         data.mval[1]= mval[1];
00332 
00333         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
00334         lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data);
00335 
00336         return data.bp;
00337 }
00338 
00339 int mouse_lattice(bContext *C, const int mval[2], int extend)
00340 {
00341         ViewContext vc;
00342         BPoint *bp= NULL;
00343 
00344         view3d_set_viewcontext(C, &vc);
00345         bp= findnearestLattvert(&vc, mval, 1);
00346 
00347         if(bp) {
00348                 if(extend==0) {
00349                         ED_setflagsLatt(vc.obedit, 0);
00350                         bp->f1 |= SELECT;
00351                 }
00352                 else
00353                         bp->f1 ^= SELECT; /* swap */
00354 
00355                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
00356 
00357                 return 1;
00358         }
00359 
00360         return 0;
00361 }
00362 
00363 /******************************** Undo *************************/
00364 
00365 typedef struct UndoLattice {
00366         BPoint *def;
00367         int pntsu, pntsv, pntsw;
00368 } UndoLattice;
00369 
00370 static void undoLatt_to_editLatt(void *data, void *edata)
00371 {
00372         UndoLattice *ult= (UndoLattice*)data;
00373         EditLatt *editlatt= (EditLatt *)edata;
00374         int a= editlatt->latt->pntsu*editlatt->latt->pntsv*editlatt->latt->pntsw;
00375 
00376         memcpy(editlatt->latt->def, ult->def, a*sizeof(BPoint));
00377 }
00378 
00379 static void *editLatt_to_undoLatt(void *edata)
00380 {
00381         UndoLattice *ult= MEM_callocN(sizeof(UndoLattice), "UndoLattice");
00382         EditLatt *editlatt= (EditLatt *)edata;
00383         
00384         ult->def= MEM_dupallocN(editlatt->latt->def);
00385         ult->pntsu= editlatt->latt->pntsu;
00386         ult->pntsv= editlatt->latt->pntsv;
00387         ult->pntsw= editlatt->latt->pntsw;
00388         
00389         return ult;
00390 }
00391 
00392 static void free_undoLatt(void *data)
00393 {
00394         UndoLattice *ult= (UndoLattice*)data;
00395 
00396         if(ult->def) MEM_freeN(ult->def);
00397         MEM_freeN(ult);
00398 }
00399 
00400 static int validate_undoLatt(void *data, void *edata)
00401 {
00402         UndoLattice *ult= (UndoLattice*)data;
00403         EditLatt *editlatt= (EditLatt *)edata;
00404 
00405         return (ult->pntsu == editlatt->latt->pntsu &&
00406                         ult->pntsv == editlatt->latt->pntsv &&
00407                         ult->pntsw == editlatt->latt->pntsw);
00408 }
00409 
00410 static void *get_editlatt(bContext *C)
00411 {
00412         Object *obedit= CTX_data_edit_object(C);
00413 
00414         if(obedit && obedit->type==OB_LATTICE) {
00415                 Lattice *lt= obedit->data;
00416                 return lt->editlatt;
00417         }
00418 
00419         return NULL;
00420 }
00421 
00422 /* and this is all the undo system needs to know */
00423 void undo_push_lattice(bContext *C, const char *name)
00424 {
00425         undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
00426 }
00427