Blender V2.61 - r43446

object_lattice.c

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