Blender V2.61 - r43446

object_shapekey.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, shapekey support
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <math.h>
00032 #include <string.h>
00033 
00034 #ifndef WIN32
00035 #include <unistd.h>
00036 #else
00037 #include <io.h>
00038 #endif   
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "BLI_blenlib.h"
00043 #include "BLI_math.h"
00044 #include "BLI_utildefines.h"
00045 
00046 #include "DNA_curve_types.h"
00047 #include "DNA_key_types.h"
00048 #include "DNA_lattice_types.h"
00049 #include "DNA_mesh_types.h"
00050 #include "DNA_meshdata_types.h"
00051 #include "DNA_scene_types.h"
00052 #include "DNA_object_types.h"
00053 
00054 #include "BKE_context.h"
00055 #include "BKE_depsgraph.h"
00056 #include "BKE_key.h"
00057 #include "BKE_library.h"
00058 #include "BKE_main.h"
00059 #include "BKE_object.h"
00060 #include "BKE_curve.h"
00061 
00062 #include "BLO_sys_types.h" // for intptr_t support
00063 
00064 #include "ED_object.h"
00065 #include "ED_mesh.h"
00066 
00067 #include "RNA_access.h"
00068 #include "RNA_define.h"
00069 
00070 #include "WM_api.h"
00071 #include "WM_types.h"
00072 
00073 #include "object_intern.h"
00074 
00075 /*********************** add shape key ***********************/
00076 
00077 static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob, int from_mix)
00078 {
00079     if(object_insert_shape_key(scene, ob, NULL, from_mix)) {
00080         Key *key= ob_get_key(ob);
00081         ob->shapenr= BLI_countlist(&key->block);
00082 
00083         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
00084     }
00085 }
00086 
00087 /*********************** remove shape key ***********************/
00088 
00089 static int ED_object_shape_key_remove(bContext *C, Object *ob)
00090 {
00091     Main *bmain= CTX_data_main(C);
00092     KeyBlock *kb, *rkb;
00093     Key *key;
00094     //IpoCurve *icu;
00095 
00096     key= ob_get_key(ob);
00097     if(key==NULL)
00098         return 0;
00099     
00100     kb= BLI_findlink(&key->block, ob->shapenr-1);
00101 
00102     if(kb) {
00103         for(rkb= key->block.first; rkb; rkb= rkb->next)
00104             if(rkb->relative == ob->shapenr-1)
00105                 rkb->relative= 0;
00106 
00107         BLI_remlink(&key->block, kb);
00108         key->totkey--;
00109         if(key->refkey== kb) {
00110             key->refkey= key->block.first;
00111 
00112             if(key->refkey) {
00113                 /* apply new basis key on original data */
00114                 switch(ob->type) {
00115                     case OB_MESH:
00116                         key_to_mesh(key->refkey, ob->data);
00117                         break;
00118                     case OB_CURVE:
00119                     case OB_SURF:
00120                         key_to_curve(key->refkey, ob->data, BKE_curve_nurbs(ob->data));
00121                         break;
00122                     case OB_LATTICE:
00123                         key_to_latt(key->refkey, ob->data);
00124                         break;
00125                 }
00126             }
00127         }
00128             
00129         if(kb->data) MEM_freeN(kb->data);
00130         MEM_freeN(kb);
00131         
00132         for(kb= key->block.first; kb; kb= kb->next)
00133             if(kb->adrcode>=ob->shapenr)
00134                 kb->adrcode--;
00135         
00136 #if 0 // XXX old animation system
00137         if(key->ipo) {
00138             
00139             for(icu= key->ipo->curve.first; icu; icu= icu->next) {
00140                 if(icu->adrcode==ob->shapenr-1) {
00141                     BLI_remlink(&key->ipo->curve, icu);
00142                     free_ipo_curve(icu);
00143                     break;
00144                 }
00145             }
00146             for(icu= key->ipo->curve.first; icu; icu= icu->next) 
00147                 if(icu->adrcode>=ob->shapenr)
00148                     icu->adrcode--;
00149         }
00150 #endif // XXX old animation system      
00151         
00152         if(ob->shapenr>1) ob->shapenr--;
00153     }
00154     
00155     if(key->totkey==0) {
00156         if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL;
00157         else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL;
00158         else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL;
00159 
00160         free_libblock_us(&(bmain->key), key);
00161     }
00162     
00163     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00164     WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
00165 
00166     return 1;
00167 }
00168 
00169 static int object_shape_key_mirror(bContext *C, Object *ob)
00170 {
00171     KeyBlock *kb;
00172     Key *key;
00173 
00174     key= ob_get_key(ob);
00175     if(key==NULL)
00176         return 0;
00177     
00178     kb= BLI_findlink(&key->block, ob->shapenr-1);
00179 
00180     if(kb) {
00181         int i1, i2;
00182         float *fp1, *fp2;
00183         float tvec[3];
00184         char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
00185 
00186 
00187         if(ob->type==OB_MESH) {
00188             Mesh *me= ob->data;
00189             MVert *mv;
00190 
00191             mesh_octree_table(ob, NULL, NULL, 's');
00192 
00193             for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) {
00194                 i2= mesh_get_x_mirror_vert(ob, i1);
00195                 if(i2==i1) {
00196                     fp1= ((float *)kb->data) + i1*3;
00197                     fp1[0] = -fp1[0];
00198                     tag_elem[i1]= 1;
00199                 }
00200                 else if(i2 != -1) {
00201                     if(tag_elem[i1]==0 && tag_elem[i2]==0) {
00202                         fp1= ((float *)kb->data) + i1*3;
00203                         fp2= ((float *)kb->data) + i2*3;
00204 
00205                         copy_v3_v3(tvec,    fp1);
00206                         copy_v3_v3(fp1, fp2);
00207                         copy_v3_v3(fp2, tvec);
00208 
00209                         /* flip x axis */
00210                         fp1[0] = -fp1[0];
00211                         fp2[0] = -fp2[0];
00212                     }
00213                     tag_elem[i1]= tag_elem[i2]= 1;
00214                 }
00215             }
00216 
00217             mesh_octree_table(ob, NULL, NULL, 'e');
00218         }
00219         else if (ob->type == OB_LATTICE) {
00220             Lattice *lt= ob->data;
00221             int i1, i2;
00222             float *fp1, *fp2;
00223             int u, v, w;
00224             /* half but found up odd value */
00225             const int pntsu_half = (((lt->pntsu / 2) + (lt->pntsu % 2))) ;
00226 
00227             /* currently editmode isnt supported by mesh so
00228              * ignore here for now too */
00229 
00230             /* if(lt->editlatt) lt= lt->editlatt->latt; */
00231 
00232             for(w=0; w<lt->pntsw; w++) {
00233                 for(v=0; v<lt->pntsv; v++) {
00234                     for(u=0; u<pntsu_half; u++) {
00235                         int u_inv= (lt->pntsu - 1) - u;
00236                         float tvec[3];
00237                         if(u == u_inv) {
00238                             i1= LT_INDEX(lt, u, v, w);
00239                             fp1= ((float *)kb->data) + i1*3;
00240                             fp1[0]= -fp1[0];
00241                         }
00242                         else {
00243                             i1= LT_INDEX(lt, u, v, w);
00244                             i2= LT_INDEX(lt, u_inv, v, w);
00245 
00246                             fp1= ((float *)kb->data) + i1*3;
00247                             fp2= ((float *)kb->data) + i2*3;
00248 
00249                             copy_v3_v3(tvec, fp1);
00250                             copy_v3_v3(fp1, fp2);
00251                             copy_v3_v3(fp2, tvec);
00252                             fp1[0]= -fp1[0];
00253                             fp2[0]= -fp2[0];
00254                         }
00255                     }
00256                 }
00257             }
00258         }
00259 
00260         MEM_freeN(tag_elem);
00261     }
00262     
00263     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00264     WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
00265 
00266     return 1;
00267 }
00268 
00269 /********************** shape key operators *********************/
00270 
00271 static int shape_key_mode_poll(bContext *C)
00272 {
00273     Object *ob= ED_object_context(C);
00274     ID *data= (ob)? ob->data: NULL;
00275     return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT);
00276 }
00277 
00278 static int shape_key_poll(bContext *C)
00279 {
00280     Object *ob= ED_object_context(C);
00281     ID *data= (ob)? ob->data: NULL;
00282     return (ob && !ob->id.lib && data && !data->lib);
00283 }
00284 
00285 static int shape_key_add_exec(bContext *C, wmOperator *op)
00286 {
00287     Scene *scene= CTX_data_scene(C);
00288     Object *ob= ED_object_context(C);
00289     int from_mix = RNA_boolean_get(op->ptr, "from_mix");
00290 
00291     ED_object_shape_key_add(C, scene, ob, from_mix);
00292 
00293     return OPERATOR_FINISHED;
00294 }
00295 
00296 void OBJECT_OT_shape_key_add(wmOperatorType *ot)
00297 {
00298     /* identifiers */
00299     ot->name= "Add Shape Key";
00300     ot->idname= "OBJECT_OT_shape_key_add";
00301     ot->description= "Add shape key to the object";
00302     
00303     /* api callbacks */
00304     ot->poll= shape_key_mode_poll;
00305     ot->exec= shape_key_add_exec;
00306 
00307     /* flags */
00308     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00309 
00310     /* properties */
00311     RNA_def_boolean(ot->srna, "from_mix", 1, "From Mix", "Create the new shape key from the existing mix of keys");
00312 }
00313 
00314 static int shape_key_remove_exec(bContext *C, wmOperator *UNUSED(op))
00315 {
00316     Object *ob= ED_object_context(C);
00317 
00318     if(!ED_object_shape_key_remove(C, ob))
00319         return OPERATOR_CANCELLED;
00320     
00321     return OPERATOR_FINISHED;
00322 }
00323 
00324 void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
00325 {
00326     /* identifiers */
00327     ot->name= "Remove Shape Key";
00328     ot->idname= "OBJECT_OT_shape_key_remove";
00329     ot->description= "Remove shape key from the object";
00330     
00331     /* api callbacks */
00332     ot->poll= shape_key_mode_poll;
00333     ot->exec= shape_key_remove_exec;
00334 
00335     /* flags */
00336     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00337 }
00338 
00339 static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
00340 {
00341     Object *ob= ED_object_context(C);
00342     Key *key= ob_get_key(ob);
00343     KeyBlock *kb= ob_get_keyblock(ob);
00344 
00345     if(!key || !kb)
00346         return OPERATOR_CANCELLED;
00347     
00348     for(kb=key->block.first; kb; kb=kb->next)
00349         kb->curval= 0.0f;
00350 
00351     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00352     WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
00353     
00354     return OPERATOR_FINISHED;
00355 }
00356 
00357 void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
00358 {
00359     /* identifiers */
00360     ot->name= "Clear Shape Keys";
00361     ot->description= "Clear weights for all shape keys";
00362     ot->idname= "OBJECT_OT_shape_key_clear";
00363     
00364     /* api callbacks */
00365     ot->poll= shape_key_poll;
00366     ot->exec= shape_key_clear_exec;
00367 
00368     /* flags */
00369     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00370 }
00371 
00372 static int shape_key_mirror_exec(bContext *C, wmOperator *UNUSED(op))
00373 {
00374     Object *ob= ED_object_context(C);
00375 
00376     if(!object_shape_key_mirror(C, ob))
00377         return OPERATOR_CANCELLED;
00378 
00379     return OPERATOR_FINISHED;
00380 }
00381 
00382 void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
00383 {
00384     /* identifiers */
00385     ot->name= "Mirror Shape Key";
00386     ot->idname= "OBJECT_OT_shape_key_mirror";
00387 
00388     /* api callbacks */
00389     ot->poll= shape_key_mode_poll;
00390     ot->exec= shape_key_mirror_exec;
00391 
00392     /* flags */
00393     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00394 }
00395 
00396 
00397 static int shape_key_move_exec(bContext *C, wmOperator *op)
00398 {
00399     Object *ob= ED_object_context(C);
00400 
00401     int type= RNA_enum_get(op->ptr, "type");
00402     Key *key= ob_get_key(ob);
00403 
00404     if(key) {
00405         KeyBlock *kb, *kb_other;
00406         int shapenr_act= ob->shapenr-1;
00407         int shapenr_swap= shapenr_act + type;
00408         kb= BLI_findlink(&key->block, shapenr_act);
00409 
00410         if((type==-1 && kb->prev==NULL) || (type==1 && kb->next==NULL)) {
00411             return OPERATOR_CANCELLED;
00412         }
00413 
00414         for(kb_other= key->block.first; kb_other; kb_other= kb_other->next) {
00415             if(kb_other->relative == shapenr_act) {
00416                 kb_other->relative += type;
00417             }
00418             else if(kb_other->relative == shapenr_swap) {
00419                 kb_other->relative -= type;
00420             }
00421         }
00422 
00423         if(type==-1) {
00424             /* move back */
00425             kb_other= kb->prev;
00426             BLI_remlink(&key->block, kb);
00427             BLI_insertlinkbefore(&key->block, kb_other, kb);
00428             ob->shapenr--;
00429         }
00430         else {
00431             /* move next */
00432             kb_other= kb->next;
00433             BLI_remlink(&key->block, kb);
00434             BLI_insertlinkafter(&key->block, kb_other, kb);
00435             ob->shapenr++;
00436         }
00437     }
00438 
00439     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00440     WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
00441 
00442     return OPERATOR_FINISHED;
00443 }
00444 
00445 void OBJECT_OT_shape_key_move(wmOperatorType *ot)
00446 {
00447     static EnumPropertyItem slot_move[] = {
00448         {-1, "UP", 0, "Up", ""},
00449         {1, "DOWN", 0, "Down", ""},
00450         {0, NULL, 0, NULL, NULL}
00451     };
00452 
00453     /* identifiers */
00454     ot->name= "Move Shape Key";
00455     ot->idname= "OBJECT_OT_shape_key_move";
00456 
00457     /* api callbacks */
00458     ot->poll= shape_key_mode_poll;
00459     ot->exec= shape_key_move_exec;
00460 
00461     /* flags */
00462     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00463 
00464     RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
00465 }
00466