python api for ID property access by Joseph Eager, copied from blender 2.4x.
[blender.git] / source / blender / editors / object / object_shapekey.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, shapekey support
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <math.h>
29 #include <string.h>
30
31 #ifndef WIN32
32 #include <unistd.h>
33 #else
34 #include <io.h>
35 #endif   
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_math.h"
41
42 #include "DNA_action_types.h"
43 #include "DNA_curve_types.h"
44 #include "DNA_ipo_types.h"
45 #include "DNA_key_types.h"
46 #include "DNA_lattice_types.h"
47 #include "DNA_mesh_types.h"
48 #include "DNA_meshdata_types.h"
49 #include "DNA_object_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_space_types.h"
53 #include "DNA_userdef_types.h"
54 #include "DNA_view2d_types.h"
55
56 #include "BKE_action.h"
57 #include "BKE_anim.h"
58 #include "BKE_context.h"
59 #include "BKE_curve.h"
60 #include "BKE_depsgraph.h"
61 #include "BKE_global.h"
62 #include "BKE_ipo.h"
63 #include "BKE_key.h"
64 #include "BKE_library.h"
65 #include "BKE_main.h"
66 #include "BKE_mesh.h"
67 #include "BKE_object.h"
68 #include "BKE_utildefines.h"
69
70 #include "BLO_sys_types.h" // for intptr_t support
71
72 #include "ED_object.h"
73 #include "ED_mesh.h"
74
75 #include "RNA_access.h"
76 #include "RNA_define.h"
77
78 #include "WM_api.h"
79 #include "WM_types.h"
80
81 #include "object_intern.h"
82
83 /************************* Mesh ************************/
84
85 void mesh_to_key(Mesh *me, KeyBlock *kb)
86 {
87         MVert *mvert;
88         float *fp;
89         int a;
90         
91         if(me->totvert==0) return;
92         
93         if(kb->data) MEM_freeN(kb->data);
94         
95         kb->data= MEM_callocN(me->key->elemsize*me->totvert, "kb->data");
96         kb->totelem= me->totvert;
97         
98         mvert= me->mvert;
99         fp= kb->data;
100         for(a=0; a<kb->totelem; a++, fp+=3, mvert++) {
101                 VECCOPY(fp, mvert->co);
102                 
103         }
104 }
105
106 void key_to_mesh(KeyBlock *kb, Mesh *me)
107 {
108         MVert *mvert;
109         float *fp;
110         int a, tot;
111         
112         mvert= me->mvert;
113         fp= kb->data;
114         
115         tot= MIN2(kb->totelem, me->totvert);
116         
117         for(a=0; a<tot; a++, fp+=3, mvert++) {
118                 VECCOPY(mvert->co, fp);
119         }
120 }
121
122 static KeyBlock *add_keyblock(Scene *scene, Key *key)
123 {
124         KeyBlock *kb;
125         float curpos= -0.1;
126         int tot;
127         
128         kb= key->block.last;
129         if(kb) curpos= kb->pos;
130         
131         kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
132         BLI_addtail(&key->block, kb);
133         kb->type= KEY_CARDINAL;
134         
135         tot= BLI_countlist(&key->block);
136         if(tot==1) strcpy(kb->name, "Basis");
137         else sprintf(kb->name, "Key %d", tot-1);
138         
139                 // XXX this is old anim system stuff? (i.e. the 'index' of the shapekey)
140         kb->adrcode= tot-1;
141         
142         key->totkey++;
143         if(key->totkey==1) key->refkey= kb;
144         
145         kb->slidermin= 0.0f;
146         kb->slidermax= 1.0f;
147         
148         // XXX kb->pos is the confusing old horizontal-line RVK crap in old IPO Editor...
149         if(key->type == KEY_RELATIVE) 
150                 kb->pos= curpos+0.1;
151         else {
152 #if 0 // XXX old animation system
153                 curpos= bsystem_time(scene, 0, (float)CFRA, 0.0);
154                 if(calc_ipo_spec(key->ipo, KEY_SPEED, &curpos)==0) {
155                         curpos /= 100.0;
156                 }
157                 kb->pos= curpos;
158                 
159                 sort_keys(key);
160 #endif // XXX old animation system
161         }
162         return kb;
163 }
164
165 static void insert_meshkey(Scene *scene, Object *ob)
166 {
167         Mesh *me= ob->data;
168         Key *key= me->key;
169         KeyBlock *kb;
170         int newkey= 0;
171
172         if(key == NULL) {
173                 key= me->key= add_key((ID *)me);
174                 key->type= KEY_RELATIVE;
175                 newkey= 1;
176         }
177         
178         kb= add_keyblock(scene, key);
179         
180         if(newkey) {
181                 /* create from mesh */
182                 mesh_to_key(me, kb);
183         }
184         else {
185                 /* copy from current values */
186                 kb->data= do_ob_key(scene, ob);
187                 kb->totelem= me->totvert;
188         }
189 }
190
191 /************************* Lattice ************************/
192
193 void latt_to_key(Lattice *lt, KeyBlock *kb)
194 {
195         BPoint *bp;
196         float *fp;
197         int a, tot;
198         
199         tot= lt->pntsu*lt->pntsv*lt->pntsw;
200         if(tot==0) return;
201         
202         if(kb->data) MEM_freeN(kb->data);
203         
204         kb->data= MEM_callocN(lt->key->elemsize*tot, "kb->data");
205         kb->totelem= tot;
206         
207         bp= lt->def;
208         fp= kb->data;
209         for(a=0; a<kb->totelem; a++, fp+=3, bp++) {
210                 VECCOPY(fp, bp->vec);
211         }
212 }
213
214 void key_to_latt(KeyBlock *kb, Lattice *lt)
215 {
216         BPoint *bp;
217         float *fp;
218         int a, tot;
219         
220         bp= lt->def;
221         fp= kb->data;
222         
223         tot= lt->pntsu*lt->pntsv*lt->pntsw;
224         tot= MIN2(kb->totelem, tot);
225         
226         for(a=0; a<tot; a++, fp+=3, bp++) {
227                 VECCOPY(bp->vec, fp);
228         }
229 }
230
231 static void insert_lattkey(Scene *scene, Object *ob)
232 {
233         Lattice *lt= ob->data;
234         Key *key= lt->key;
235         KeyBlock *kb;
236         int newkey= 0;
237         
238         if(key==NULL) {
239                 key= lt->key= add_key( (ID *)lt);
240                 key->type= KEY_RELATIVE;
241                 newkey= 1;
242         }
243
244         kb= add_keyblock(scene, key);
245         
246         if(newkey) {
247                 /* create from lattice */
248                 latt_to_key(lt, kb);
249         }
250         else {
251                 /* copy from current values */
252                 kb->totelem= lt->pntsu*lt->pntsv*lt->pntsw;
253                 kb->data= do_ob_key(scene, ob);
254         }
255 }
256
257 /************************* Curve ************************/
258
259 void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
260 {
261         Nurb *nu;
262         BezTriple *bezt;
263         BPoint *bp;
264         float *fp;
265         int a, tot;
266         
267         /* count */
268         tot= count_curveverts(nurb);
269         if(tot==0) return;
270         
271         if(kb->data) MEM_freeN(kb->data);
272         
273         kb->data= MEM_callocN(cu->key->elemsize*tot, "kb->data");
274         kb->totelem= tot;
275         
276         nu= nurb->first;
277         fp= kb->data;
278         while(nu) {
279                 
280                 if(nu->bezt) {
281                         bezt= nu->bezt;
282                         a= nu->pntsu;
283                         while(a--) {
284                                 VECCOPY(fp, bezt->vec[0]);
285                                 fp+= 3;
286                                 VECCOPY(fp, bezt->vec[1]);
287                                 fp+= 3;
288                                 VECCOPY(fp, bezt->vec[2]);
289                                 fp+= 3;
290                                 fp[0]= bezt->alfa;
291                                 fp+= 3; /* alphas */
292                                 bezt++;
293                         }
294                 }
295                 else {
296                         bp= nu->bp;
297                         a= nu->pntsu*nu->pntsv;
298                         while(a--) {
299                                 VECCOPY(fp, bp->vec);
300                                 fp[3]= bp->alfa;
301                                 
302                                 fp+= 4;
303                                 bp++;
304                         }
305                 }
306                 nu= nu->next;
307         }
308 }
309
310 void key_to_curve(KeyBlock *kb, Curve  *cu, ListBase *nurb)
311 {
312         Nurb *nu;
313         BezTriple *bezt;
314         BPoint *bp;
315         float *fp;
316         int a, tot;
317         
318         nu= nurb->first;
319         fp= kb->data;
320         
321         tot= count_curveverts(nurb);
322
323         tot= MIN2(kb->totelem, tot);
324         
325         while(nu && tot>0) {
326                 
327                 if(nu->bezt) {
328                         bezt= nu->bezt;
329                         a= nu->pntsu;
330                         while(a-- && tot>0) {
331                                 VECCOPY(bezt->vec[0], fp);
332                                 fp+= 3;
333                                 VECCOPY(bezt->vec[1], fp);
334                                 fp+= 3;
335                                 VECCOPY(bezt->vec[2], fp);
336                                 fp+= 3;
337                                 bezt->alfa= fp[0];
338                                 fp+= 3; /* alphas */
339                         
340                                 tot-= 3;
341                                 bezt++;
342                         }
343                 }
344                 else {
345                         bp= nu->bp;
346                         a= nu->pntsu*nu->pntsv;
347                         while(a-- && tot>0) {
348                                 VECCOPY(bp->vec, fp);
349                                 bp->alfa= fp[3];
350                                 
351                                 fp+= 4;
352                                 tot--;
353                                 bp++;
354                         }
355                 }
356                 nu= nu->next;
357         }
358 }
359
360
361 static void insert_curvekey(Scene *scene, Object *ob)
362 {
363         Curve *cu= ob->data;
364         Key *key= cu->key;
365         KeyBlock *kb;
366         ListBase *lb= (cu->editnurb)? cu->editnurb: &cu->nurb;
367         int newkey= 0;
368         
369         if(key==NULL) {
370                 key= cu->key= add_key( (ID *)cu);
371                 key->type = KEY_RELATIVE;
372                 newkey= 1;
373         }
374         
375         kb= add_keyblock(scene, key);
376         
377         if(newkey) {
378                 /* create from curve */
379                 curve_to_key(cu, kb, lb);
380         }
381         else {
382                 /* copy from current values */
383                 kb->totelem= count_curveverts(lb);
384                 kb->data= do_ob_key(scene, ob);
385         }
386
387 }
388
389 /*********************** add shape key ***********************/
390
391 static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob)
392 {
393         Key *key;
394
395         if(ob->type==OB_MESH) insert_meshkey(scene, ob);
396         else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(scene, ob);
397         else if(ob->type==OB_LATTICE) insert_lattkey(scene, ob);
398
399         key= ob_get_key(ob);
400         ob->shapenr= BLI_countlist(&key->block);
401
402         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
403 }
404
405 /*********************** remove shape key ***********************/
406
407 static int ED_object_shape_key_remove(bContext *C, Object *ob)
408 {
409         Main *bmain= CTX_data_main(C);
410         KeyBlock *kb, *rkb;
411         Key *key;
412         //IpoCurve *icu;
413
414         key= ob_get_key(ob);
415         if(key==NULL)
416                 return 0;
417         
418         kb= BLI_findlink(&key->block, ob->shapenr-1);
419
420         if(kb) {
421                 for(rkb= key->block.first; rkb; rkb= rkb->next)
422                         if(rkb->relative == ob->shapenr-1)
423                                 rkb->relative= 0;
424
425                 BLI_remlink(&key->block, kb);
426                 key->totkey--;
427                 if(key->refkey== kb)
428                         key->refkey= key->block.first;
429                         
430                 if(kb->data) MEM_freeN(kb->data);
431                 MEM_freeN(kb);
432                 
433                 for(kb= key->block.first; kb; kb= kb->next)
434                         if(kb->adrcode>=ob->shapenr)
435                                 kb->adrcode--;
436                 
437 #if 0 // XXX old animation system
438                 if(key->ipo) {
439                         
440                         for(icu= key->ipo->curve.first; icu; icu= icu->next) {
441                                 if(icu->adrcode==ob->shapenr-1) {
442                                         BLI_remlink(&key->ipo->curve, icu);
443                                         free_ipo_curve(icu);
444                                         break;
445                                 }
446                         }
447                         for(icu= key->ipo->curve.first; icu; icu= icu->next) 
448                                 if(icu->adrcode>=ob->shapenr)
449                                         icu->adrcode--;
450                 }
451 #endif // XXX old animation system              
452                 
453                 if(ob->shapenr>1) ob->shapenr--;
454         }
455         
456         if(key->totkey==0) {
457                 if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL;
458                 else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL;
459                 else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL;
460
461                 free_libblock_us(&(bmain->key), key);
462         }
463         
464         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
465         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
466
467         return 1;
468 }
469
470 static int ED_object_shape_key_mirror(bContext *C, Scene *scene, Object *ob)
471 {
472         KeyBlock *kb;
473         Key *key;
474
475         key= ob_get_key(ob);
476         if(key==NULL)
477                 return 0;
478         
479         kb= BLI_findlink(&key->block, ob->shapenr-1);
480
481         if(kb) {
482                 int i1, i2;
483                 float *fp1, *fp2;
484                 float tvec[3];
485                 char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
486
487
488                 if(ob->type==OB_MESH) {
489                         Mesh *me= ob->data;
490                         MVert *mv;
491
492                         mesh_octree_table(ob, NULL, NULL, 's');
493
494                         for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) {
495                                 i2= mesh_get_x_mirror_vert(ob, i1);
496                                 if(i2==i1) {
497                                         fp1= ((float *)kb->data) + i1*3;
498                                         fp1[0] = -fp1[0];
499                                         tag_elem[i1]= 1;
500                                 }
501                                 else if(i2 != -1) {
502                                         if(tag_elem[i1]==0 && tag_elem[i2]==0) {
503                                                 fp1= ((float *)kb->data) + i1*3;
504                                                 fp2= ((float *)kb->data) + i2*3;
505
506                                                 VECCOPY(tvec,   fp1);
507                                                 VECCOPY(fp1,    fp2);
508                                                 VECCOPY(fp2,    tvec);
509
510                                                 /* flip x axis */
511                                                 fp1[0] = -fp1[0];
512                                                 fp2[0] = -fp2[0];
513                                         }
514                                         tag_elem[i1]= tag_elem[i2]= 1;
515                                 }
516                         }
517
518                         mesh_octree_table(ob, NULL, NULL, 'e');
519                 }
520                 /* todo, other types? */
521
522                 MEM_freeN(tag_elem);
523         }
524         
525         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
526         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
527
528         return 1;
529 }
530
531 /********************** shape key operators *********************/
532
533 static int shape_key_mode_poll(bContext *C)
534 {
535         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
536         ID *data= (ob)? ob->data: NULL;
537         return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT);
538 }
539
540 static int shape_key_poll(bContext *C)
541 {
542         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
543         ID *data= (ob)? ob->data: NULL;
544         return (ob && !ob->id.lib && data && !data->lib);
545 }
546
547 static int shape_key_add_exec(bContext *C, wmOperator *op)
548 {
549         Scene *scene= CTX_data_scene(C);
550         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
551
552         ED_object_shape_key_add(C, scene, ob);
553         
554         return OPERATOR_FINISHED;
555 }
556
557 void OBJECT_OT_shape_key_add(wmOperatorType *ot)
558 {
559         /* identifiers */
560         ot->name= "Add Shape Key";
561         ot->name= "Add shape key to the object.";
562         ot->idname= "OBJECT_OT_shape_key_add";
563         
564         /* api callbacks */
565         ot->poll= shape_key_mode_poll;
566         ot->exec= shape_key_add_exec;
567
568         /* flags */
569         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
570 }
571
572 static int shape_key_remove_exec(bContext *C, wmOperator *op)
573 {
574         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
575
576         if(!ED_object_shape_key_remove(C, ob))
577                 return OPERATOR_CANCELLED;
578         
579         return OPERATOR_FINISHED;
580 }
581
582 void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
583 {
584         /* identifiers */
585         ot->name= "Remove Shape Key";
586         ot->name= "Remove shape key from the object.";
587         ot->idname= "OBJECT_OT_shape_key_remove";
588         
589         /* api callbacks */
590         ot->poll= shape_key_mode_poll;
591         ot->exec= shape_key_remove_exec;
592
593         /* flags */
594         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
595 }
596
597 static int shape_key_clear_exec(bContext *C, wmOperator *op)
598 {
599         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
600         Key *key= ob_get_key(ob);
601         KeyBlock *kb= ob_get_keyblock(ob);
602
603         if(!key || !kb)
604                 return OPERATOR_CANCELLED;
605         
606         for(kb=key->block.first; kb; kb=kb->next)
607                 kb->curval= 0.0f;
608
609         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
610         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
611         
612         return OPERATOR_FINISHED;
613 }
614
615 void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
616 {
617         /* identifiers */
618         ot->name= "Clear Shape Keys";
619         ot->description= "Clear weights for all shape keys.";
620         ot->idname= "OBJECT_OT_shape_key_clear";
621         
622         /* api callbacks */
623         ot->poll= shape_key_poll;
624         ot->exec= shape_key_clear_exec;
625
626         /* flags */
627         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
628 }
629
630 static int shape_key_mirror_exec(bContext *C, wmOperator *op)
631 {
632         Scene *scene= CTX_data_scene(C);
633         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
634
635         if(!ED_object_shape_key_mirror(C, scene, ob))
636                 return OPERATOR_CANCELLED;
637
638         return OPERATOR_FINISHED;
639 }
640
641 void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
642 {
643         /* identifiers */
644         ot->name= "Mirror Shape Key";
645         ot->idname= "OBJECT_OT_shape_key_mirror";
646
647         /* api callbacks */
648         ot->poll= shape_key_mode_poll;
649         ot->exec= shape_key_mirror_exec;
650
651         /* flags */
652         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
653 }
654
655
656 static int shape_key_move_exec(bContext *C, wmOperator *op)
657 {
658         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
659
660         int type= RNA_enum_get(op->ptr, "type");
661         Key *key= ob_get_key(ob);
662
663         if(key) {
664                 KeyBlock *kb, *kb_other;
665                 kb= BLI_findlink(&key->block, ob->shapenr-1);
666
667                 if(type==-1) {
668                         /* move back */
669                         if(kb->prev) {
670                                 kb_other= kb->prev;
671                                 BLI_remlink(&key->block, kb);
672                                 BLI_insertlinkbefore(&key->block, kb_other, kb);
673                                 ob->shapenr--;
674                         }
675                 }
676                 else {
677                         /* move next */
678                         if(kb->next) {
679                                 kb_other= kb->next;
680                                 BLI_remlink(&key->block, kb);
681                                 BLI_insertlinkafter(&key->block, kb_other, kb);
682                                 ob->shapenr++;
683                         }
684                 }
685         }
686
687         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
688         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
689
690         return OPERATOR_FINISHED;
691 }
692
693 void OBJECT_OT_shape_key_move(wmOperatorType *ot)
694 {
695         static EnumPropertyItem slot_move[] = {
696                 {-1, "UP", 0, "Up", ""},
697                 {1, "DOWN", 0, "Down", ""},
698                 {0, NULL, 0, NULL, NULL}
699         };
700
701         /* identifiers */
702         ot->name= "Move Shape Key";
703         ot->idname= "OBJECT_OT_shape_key_move";
704
705         /* api callbacks */
706         ot->poll= shape_key_mode_poll;
707         ot->exec= shape_key_move_exec;
708
709         /* flags */
710         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
711
712         RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
713 }
714