Logic UI and Operators: adjusts on Layout + copy properties operator + fix on copy...
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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_curve_types.h"
43 #include "DNA_key_types.h"
44 #include "DNA_lattice_types.h"
45 #include "DNA_mesh_types.h"
46 #include "DNA_meshdata_types.h"
47 #include "DNA_scene_types.h"
48
49 #include "BKE_action.h"
50 #include "BKE_anim.h"
51 #include "BKE_context.h"
52 #include "BKE_curve.h"
53 #include "BKE_depsgraph.h"
54 #include "BKE_global.h"
55 #include "BKE_ipo.h"
56 #include "BKE_key.h"
57 #include "BKE_library.h"
58 #include "BKE_main.h"
59 #include "BKE_mesh.h"
60 #include "BKE_object.h"
61 #include "BKE_utildefines.h"
62
63 #include "BLO_sys_types.h" // for intptr_t support
64
65 #include "ED_mesh.h"
66
67 #include "RNA_access.h"
68 #include "RNA_define.h"
69
70 #include "WM_api.h"
71 #include "WM_types.h"
72
73 #include "object_intern.h"
74
75 /*********************** add shape key ***********************/
76
77 static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob, int from_mix)
78 {
79         if(object_insert_shape_key(scene, ob, NULL, from_mix)) {
80                 Key *key= ob_get_key(ob);
81                 ob->shapenr= BLI_countlist(&key->block);
82
83                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
84         }
85 }
86
87 /*********************** remove shape key ***********************/
88
89 static int ED_object_shape_key_remove(bContext *C, Object *ob)
90 {
91         Main *bmain= CTX_data_main(C);
92         KeyBlock *kb, *rkb;
93         Key *key;
94         //IpoCurve *icu;
95
96         key= ob_get_key(ob);
97         if(key==NULL)
98                 return 0;
99         
100         kb= BLI_findlink(&key->block, ob->shapenr-1);
101
102         if(kb) {
103                 for(rkb= key->block.first; rkb; rkb= rkb->next)
104                         if(rkb->relative == ob->shapenr-1)
105                                 rkb->relative= 0;
106
107                 BLI_remlink(&key->block, kb);
108                 key->totkey--;
109                 if(key->refkey== kb)
110                         key->refkey= key->block.first;
111                         
112                 if(kb->data) MEM_freeN(kb->data);
113                 MEM_freeN(kb);
114                 
115                 for(kb= key->block.first; kb; kb= kb->next)
116                         if(kb->adrcode>=ob->shapenr)
117                                 kb->adrcode--;
118                 
119 #if 0 // XXX old animation system
120                 if(key->ipo) {
121                         
122                         for(icu= key->ipo->curve.first; icu; icu= icu->next) {
123                                 if(icu->adrcode==ob->shapenr-1) {
124                                         BLI_remlink(&key->ipo->curve, icu);
125                                         free_ipo_curve(icu);
126                                         break;
127                                 }
128                         }
129                         for(icu= key->ipo->curve.first; icu; icu= icu->next) 
130                                 if(icu->adrcode>=ob->shapenr)
131                                         icu->adrcode--;
132                 }
133 #endif // XXX old animation system              
134                 
135                 if(ob->shapenr>1) ob->shapenr--;
136         }
137         
138         if(key->totkey==0) {
139                 if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL;
140                 else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL;
141                 else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL;
142
143                 free_libblock_us(&(bmain->key), key);
144         }
145         
146         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
147         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
148
149         return 1;
150 }
151
152 static int ED_object_shape_key_mirror(bContext *C, Scene *scene, Object *ob)
153 {
154         KeyBlock *kb;
155         Key *key;
156
157         key= ob_get_key(ob);
158         if(key==NULL)
159                 return 0;
160         
161         kb= BLI_findlink(&key->block, ob->shapenr-1);
162
163         if(kb) {
164                 int i1, i2;
165                 float *fp1, *fp2;
166                 float tvec[3];
167                 char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
168
169
170                 if(ob->type==OB_MESH) {
171                         Mesh *me= ob->data;
172                         MVert *mv;
173
174                         mesh_octree_table(ob, NULL, NULL, 's');
175
176                         for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) {
177                                 i2= mesh_get_x_mirror_vert(ob, i1);
178                                 if(i2==i1) {
179                                         fp1= ((float *)kb->data) + i1*3;
180                                         fp1[0] = -fp1[0];
181                                         tag_elem[i1]= 1;
182                                 }
183                                 else if(i2 != -1) {
184                                         if(tag_elem[i1]==0 && tag_elem[i2]==0) {
185                                                 fp1= ((float *)kb->data) + i1*3;
186                                                 fp2= ((float *)kb->data) + i2*3;
187
188                                                 VECCOPY(tvec,   fp1);
189                                                 VECCOPY(fp1,    fp2);
190                                                 VECCOPY(fp2,    tvec);
191
192                                                 /* flip x axis */
193                                                 fp1[0] = -fp1[0];
194                                                 fp2[0] = -fp2[0];
195                                         }
196                                         tag_elem[i1]= tag_elem[i2]= 1;
197                                 }
198                         }
199
200                         mesh_octree_table(ob, NULL, NULL, 'e');
201                 }
202                 /* todo, other types? */
203
204                 MEM_freeN(tag_elem);
205         }
206         
207         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
208         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
209
210         return 1;
211 }
212
213 /********************** shape key operators *********************/
214
215 static int shape_key_mode_poll(bContext *C)
216 {
217         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
218         ID *data= (ob)? ob->data: NULL;
219         return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT);
220 }
221
222 static int shape_key_poll(bContext *C)
223 {
224         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
225         ID *data= (ob)? ob->data: NULL;
226         return (ob && !ob->id.lib && data && !data->lib);
227 }
228
229 static int shape_key_add_exec(bContext *C, wmOperator *op)
230 {
231         Scene *scene= CTX_data_scene(C);
232         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
233         int from_mix = RNA_boolean_get(op->ptr, "from_mix");
234
235         ED_object_shape_key_add(C, scene, ob, from_mix);
236
237         return OPERATOR_FINISHED;
238 }
239
240 void OBJECT_OT_shape_key_add(wmOperatorType *ot)
241 {
242         /* identifiers */
243         ot->name= "Add Shape Key";
244         ot->name= "Add shape key to the object.";
245         ot->idname= "OBJECT_OT_shape_key_add";
246         
247         /* api callbacks */
248         ot->poll= shape_key_mode_poll;
249         ot->exec= shape_key_add_exec;
250
251         /* flags */
252         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
253
254         /* properties */
255         RNA_def_boolean(ot->srna, "from_mix", 1, "From Mix", "Create the new shape key from the existing mix of keys.");
256 }
257
258 static int shape_key_remove_exec(bContext *C, wmOperator *op)
259 {
260         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
261
262         if(!ED_object_shape_key_remove(C, ob))
263                 return OPERATOR_CANCELLED;
264         
265         return OPERATOR_FINISHED;
266 }
267
268 void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
269 {
270         /* identifiers */
271         ot->name= "Remove Shape Key";
272         ot->name= "Remove shape key from the object.";
273         ot->idname= "OBJECT_OT_shape_key_remove";
274         
275         /* api callbacks */
276         ot->poll= shape_key_mode_poll;
277         ot->exec= shape_key_remove_exec;
278
279         /* flags */
280         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
281 }
282
283 static int shape_key_clear_exec(bContext *C, wmOperator *op)
284 {
285         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
286         Key *key= ob_get_key(ob);
287         KeyBlock *kb= ob_get_keyblock(ob);
288
289         if(!key || !kb)
290                 return OPERATOR_CANCELLED;
291         
292         for(kb=key->block.first; kb; kb=kb->next)
293                 kb->curval= 0.0f;
294
295         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
296         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
297         
298         return OPERATOR_FINISHED;
299 }
300
301 void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
302 {
303         /* identifiers */
304         ot->name= "Clear Shape Keys";
305         ot->description= "Clear weights for all shape keys";
306         ot->idname= "OBJECT_OT_shape_key_clear";
307         
308         /* api callbacks */
309         ot->poll= shape_key_poll;
310         ot->exec= shape_key_clear_exec;
311
312         /* flags */
313         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
314 }
315
316 static int shape_key_mirror_exec(bContext *C, wmOperator *op)
317 {
318         Scene *scene= CTX_data_scene(C);
319         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
320
321         if(!ED_object_shape_key_mirror(C, scene, ob))
322                 return OPERATOR_CANCELLED;
323
324         return OPERATOR_FINISHED;
325 }
326
327 void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
328 {
329         /* identifiers */
330         ot->name= "Mirror Shape Key";
331         ot->idname= "OBJECT_OT_shape_key_mirror";
332
333         /* api callbacks */
334         ot->poll= shape_key_mode_poll;
335         ot->exec= shape_key_mirror_exec;
336
337         /* flags */
338         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
339 }
340
341
342 static int shape_key_move_exec(bContext *C, wmOperator *op)
343 {
344         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
345
346         int type= RNA_enum_get(op->ptr, "type");
347         Key *key= ob_get_key(ob);
348
349         if(key) {
350                 KeyBlock *kb, *kb_other;
351                 int shapenr_act= ob->shapenr-1;
352                 int shapenr_swap= shapenr_act + type;
353                 kb= BLI_findlink(&key->block, shapenr_act);
354
355                 if((type==-1 && kb->prev==NULL) || (type==1 && kb->next==NULL)) {
356                         return OPERATOR_CANCELLED;
357                 }
358
359                 for(kb_other= key->block.first; kb_other; kb_other= kb_other->next) {
360                         if(kb_other->relative == shapenr_act) {
361                                 kb_other->relative += type;
362                         }
363                         else if(kb_other->relative == shapenr_swap) {
364                                 kb_other->relative -= type;
365                         }
366                 }
367
368                 if(type==-1) {
369                         /* move back */
370                         kb_other= kb->prev;
371                         BLI_remlink(&key->block, kb);
372                         BLI_insertlinkbefore(&key->block, kb_other, kb);
373                         ob->shapenr--;
374                 }
375                 else {
376                         /* move next */
377                         kb_other= kb->next;
378                         BLI_remlink(&key->block, kb);
379                         BLI_insertlinkafter(&key->block, kb_other, kb);
380                         ob->shapenr++;
381                 }
382         }
383
384         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
385         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
386
387         return OPERATOR_FINISHED;
388 }
389
390 void OBJECT_OT_shape_key_move(wmOperatorType *ot)
391 {
392         static EnumPropertyItem slot_move[] = {
393                 {-1, "UP", 0, "Up", ""},
394                 {1, "DOWN", 0, "Down", ""},
395                 {0, NULL, 0, NULL, NULL}
396         };
397
398         /* identifiers */
399         ot->name= "Move Shape Key";
400         ot->idname= "OBJECT_OT_shape_key_move";
401
402         /* api callbacks */
403         ot->poll= shape_key_mode_poll;
404         ot->exec= shape_key_move_exec;
405
406         /* flags */
407         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
408
409         RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
410 }
411