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