Bugfix #20382
[blender.git] / source / blender / editors / object / object_transform.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, 2002-2008 full recode
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "DNA_anim_types.h"
32 #include "DNA_armature_types.h"
33 #include "DNA_key_types.h"
34 #include "DNA_meshdata_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_group_types.h"
38
39 #include "BLI_math.h"
40 #include "BLI_editVert.h"
41 #include "BLI_listbase.h"
42
43 #include "BKE_context.h"
44 #include "BKE_curve.h"
45 #include "BKE_depsgraph.h"
46 #include "BKE_main.h"
47 #include "BKE_mesh.h"
48 #include "BKE_object.h"
49 #include "BKE_report.h"
50 #include "BKE_multires.h"
51
52 #include "RNA_define.h"
53 #include "RNA_access.h"
54
55 #include "WM_api.h"
56 #include "WM_types.h"
57
58 #include "ED_armature.h"
59 #include "ED_keyframing.h"
60 #include "ED_mesh.h"
61 #include "ED_screen.h"
62 #include "ED_view3d.h"
63
64 #include "object_intern.h"
65
66 /*************************** Clear Transformation ****************************/
67
68 static int object_location_clear_exec(bContext *C, wmOperator *UNUSED(op))
69 {
70         Main *bmain = CTX_data_main(C);
71         Scene *scene = CTX_data_scene(C);
72         
73         /* get KeyingSet to use */
74         KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Location");
75         
76         /* clear location of selected objects if not in weight-paint mode */
77         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
78                 if (!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
79                         /* clear location if not locked */
80                         if ((ob->protectflag & OB_LOCK_LOCX)==0)
81                                 ob->loc[0]= ob->dloc[0]= 0.0f;
82                         if ((ob->protectflag & OB_LOCK_LOCY)==0)
83                                 ob->loc[1]= ob->dloc[1]= 0.0f;
84                         if ((ob->protectflag & OB_LOCK_LOCZ)==0)
85                                 ob->loc[2]= ob->dloc[2]= 0.0f;
86                                 
87                         /* auto keyframing */
88                         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
89                                 ListBase dsources = {NULL, NULL};
90                                 
91                                 /* now insert the keyframe(s) using the Keying Set
92                                  *      1) add datasource override for the PoseChannel
93                                  *      2) insert keyframes
94                                  *      3) free the extra info 
95                                  */
96                                 ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL); 
97                                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
98                                 BLI_freelistN(&dsources);
99                         }
100                 }
101                 
102                 ob->recalc |= OB_RECALC_OB;
103         }
104         CTX_DATA_END;
105         
106         /* this is needed so children are also updated */
107         DAG_ids_flush_update(bmain, 0);
108
109         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
110
111         return OPERATOR_FINISHED;
112 }
113
114 void OBJECT_OT_location_clear(wmOperatorType *ot)
115 {
116         /* identifiers */
117         ot->name= "Clear Location";
118         ot->description = "Clear the object's location";
119         ot->idname= "OBJECT_OT_location_clear";
120         
121         /* api callbacks */
122         ot->exec= object_location_clear_exec;
123         ot->poll= ED_operator_scene_editable;
124         
125         /* flags */
126         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
127 }
128
129 static int object_rotation_clear_exec(bContext *C, wmOperator *UNUSED(op))
130 {
131         Main *bmain= CTX_data_main(C);
132         Scene *scene= CTX_data_scene(C);
133         
134         /* get KeyingSet to use */
135         KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Rotation");
136         
137         /* clear rotation of selected objects if not in weight-paint mode */
138         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
139                 if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
140                         /* clear rotations that aren't locked */
141                         if (ob->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
142                                 if (ob->protectflag & OB_LOCK_ROT4D) {
143                                         /* perform clamping on a component by component basis */
144                                         if (ob->rotmode == ROT_MODE_AXISANGLE) {
145                                                 if ((ob->protectflag & OB_LOCK_ROTW) == 0)
146                                                         ob->rotAngle= 0.0f;
147                                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0)
148                                                         ob->rotAxis[0]= 0.0f;
149                                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0)
150                                                         ob->rotAxis[1]= 0.0f;
151                                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0)
152                                                         ob->rotAxis[2]= 0.0f;
153                                                         
154                                                 /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
155                                                 if (IS_EQ(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQ(ob->rotAxis[1], ob->rotAxis[2]))
156                                                         ob->rotAxis[1] = 1.0f;
157                                         }
158                                         else if (ob->rotmode == ROT_MODE_QUAT) {
159                                                 if ((ob->protectflag & OB_LOCK_ROTW) == 0)
160                                                         ob->quat[0]= 1.0f;
161                                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0)
162                                                         ob->quat[1]= 0.0f;
163                                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0)
164                                                         ob->quat[2]= 0.0f;
165                                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0)
166                                                         ob->quat[3]= 0.0f;
167                                         }
168                                         else {
169                                                 /* the flag may have been set for the other modes, so just ignore the extra flag... */
170                                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0)
171                                                         ob->rot[0]= 0.0f;
172                                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0)
173                                                         ob->rot[1]= 0.0f;
174                                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0)
175                                                         ob->rot[2]= 0.0f;
176                                         }
177                                 }
178                                 else {
179                                         /* perform clamping using euler form (3-components) */
180                                         float eul[3], oldeul[3], quat1[4] = {0};
181                                         
182                                         if (ob->rotmode == ROT_MODE_QUAT) {
183                                                 QUATCOPY(quat1, ob->quat);
184                                                 quat_to_eul( oldeul,ob->quat);
185                                         }
186                                         else if (ob->rotmode == ROT_MODE_AXISANGLE) {
187                                                 axis_angle_to_eulO( oldeul, EULER_ORDER_DEFAULT,ob->rotAxis, ob->rotAngle);
188                                         }
189                                         else {
190                                                 copy_v3_v3(oldeul, ob->rot);
191                                         }
192                                         
193                                         eul[0]= eul[1]= eul[2]= 0.0f;
194                                         
195                                         if (ob->protectflag & OB_LOCK_ROTX)
196                                                 eul[0]= oldeul[0];
197                                         if (ob->protectflag & OB_LOCK_ROTY)
198                                                 eul[1]= oldeul[1];
199                                         if (ob->protectflag & OB_LOCK_ROTZ)
200                                                 eul[2]= oldeul[2];
201                                         
202                                         if (ob->rotmode == ROT_MODE_QUAT) {
203                                                 eul_to_quat( ob->quat,eul);
204                                                 /* quaternions flip w sign to accumulate rotations correctly */
205                                                 if ((quat1[0]<0.0f && ob->quat[0]>0.0f) || (quat1[0]>0.0f && ob->quat[0]<0.0f)) {
206                                                         mul_qt_fl(ob->quat, -1.0f);
207                                                 }
208                                         }
209                                         else if (ob->rotmode == ROT_MODE_AXISANGLE) {
210                                                 eulO_to_axis_angle( ob->rotAxis, &ob->rotAngle,eul, EULER_ORDER_DEFAULT);
211                                         }
212                                         else {
213                                                 copy_v3_v3(ob->rot, eul);
214                                         }
215                                 }
216                         }                                                // Duplicated in source/blender/editors/armature/editarmature.c
217                         else { 
218                                 if (ob->rotmode == ROT_MODE_QUAT) {
219                                         ob->quat[1]=ob->quat[2]=ob->quat[3]= 0.0f; 
220                                         ob->quat[0]= 1.0f;
221                                 }
222                                 else if (ob->rotmode == ROT_MODE_AXISANGLE) {
223                                         /* by default, make rotation of 0 radians around y-axis (roll) */
224                                         ob->rotAxis[0]=ob->rotAxis[2]=ob->rotAngle= 0.0f;
225                                         ob->rotAxis[1]= 1.0f;
226                                 }
227                                 else {
228                                         ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0f;
229                                 }
230                         }
231                         
232                         /* auto keyframing */
233                         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
234                                 ListBase dsources = {NULL, NULL};
235                                 
236                                 /* now insert the keyframe(s) using the Keying Set
237                                  *      1) add datasource override for the PoseChannel
238                                  *      2) insert keyframes
239                                  *      3) free the extra info 
240                                  */
241                                 ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL); 
242                                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
243                                 BLI_freelistN(&dsources);
244                         }
245                 }
246                 
247                 ob->recalc |= OB_RECALC_OB;
248         }
249         CTX_DATA_END;
250         
251         /* this is needed so children are also updated */
252         DAG_ids_flush_update(bmain, 0);
253
254         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
255         
256         return OPERATOR_FINISHED;
257 }
258
259 void OBJECT_OT_rotation_clear(wmOperatorType *ot)
260 {
261         /* identifiers */
262         ot->name= "Clear Rotation";
263         ot->description = "Clear the object's rotation";
264         ot->idname= "OBJECT_OT_rotation_clear";
265         
266         /* api callbacks */
267         ot->exec= object_rotation_clear_exec;
268         ot->poll= ED_operator_scene_editable;
269         
270         /* flags */
271         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
272 }
273
274 static int object_scale_clear_exec(bContext *C, wmOperator *UNUSED(op))
275 {
276         Main *bmain= CTX_data_main(C);
277         Scene *scene= CTX_data_scene(C);
278         
279         /* get KeyingSet to use */
280         KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Scaling");
281         
282         /* clear scales of selected objects if not in weight-paint mode */
283         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
284                 if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
285                         /* clear scale factors which are not locked */
286                         if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
287                                 ob->dsize[0]= 0.0f;
288                                 ob->size[0]= 1.0f;
289                         }
290                         if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
291                                 ob->dsize[1]= 0.0f;
292                                 ob->size[1]= 1.0f;
293                         }
294                         if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
295                                 ob->dsize[2]= 0.0f;
296                                 ob->size[2]= 1.0f;
297                         }
298                         
299                         /* auto keyframing */
300                         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
301                                 ListBase dsources = {NULL, NULL};
302                                 
303                                 /* now insert the keyframe(s) using the Keying Set
304                                  *      1) add datasource override for the PoseChannel
305                                  *      2) insert keyframes
306                                  *      3) free the extra info 
307                                  */
308                                 ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL); 
309                                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
310                                 BLI_freelistN(&dsources);
311                         }
312                 }
313                 ob->recalc |= OB_RECALC_OB;
314         }
315         CTX_DATA_END;
316         
317         /* this is needed so children are also updated */
318         DAG_ids_flush_update(bmain, 0);
319
320         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
321         
322         return OPERATOR_FINISHED;
323 }
324
325 void OBJECT_OT_scale_clear(wmOperatorType *ot)
326 {
327         /* identifiers */
328         ot->name= "Clear Scale";
329         ot->description = "Clear the object's scale";
330         ot->idname= "OBJECT_OT_scale_clear";
331         
332         /* api callbacks */
333         ot->exec= object_scale_clear_exec;
334         ot->poll= ED_operator_scene_editable;
335         
336         /* flags */
337         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
338 }
339
340 static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
341 {
342         Main *bmain= CTX_data_main(C);
343         float *v1, *v3, mat[3][3];
344         int armature_clear= 0;
345
346         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
347                 if(ob->parent) {
348                         v1= ob->loc;
349                         v3= ob->parentinv[3];
350                         
351                         copy_m3_m4(mat, ob->parentinv);
352                         negate_v3_v3(v3, v1);
353                         mul_m3_v3(mat, v3);
354                 }
355                 ob->recalc |= OB_RECALC_OB;
356         }
357         CTX_DATA_END;
358
359         if(armature_clear==0) /* in this case flush was done */
360                 DAG_ids_flush_update(bmain, 0);
361         
362         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
363         
364         return OPERATOR_FINISHED;
365 }
366
367 void OBJECT_OT_origin_clear(wmOperatorType *ot)
368 {
369         /* identifiers */
370         ot->name= "Clear Origin";
371         ot->description = "Clear the object's origin";
372         ot->idname= "OBJECT_OT_origin_clear";
373         
374         /* api callbacks */
375         ot->exec= object_origin_clear_exec;
376         ot->poll= ED_operator_scene_editable;
377         
378         /* flags */
379         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
380 }
381
382 /*************************** Apply Transformation ****************************/
383
384 /* use this when the loc/size/rot of the parent has changed but the children
385  * should stay in the same place, e.g. for apply-size-rot or object center */
386 static void ignore_parent_tx(Main *bmain, Scene *scene, Object *ob ) 
387 {
388         Object workob;
389         Object *ob_child;
390         
391         /* a change was made, adjust the children to compensate */
392         for(ob_child=bmain->object.first; ob_child; ob_child=ob_child->id.next) {
393                 if(ob_child->parent == ob) {
394                         object_apply_mat4(ob_child, ob_child->obmat, TRUE, FALSE);
395                         what_does_parent(scene, ob_child, &workob);
396                         invert_m4_m4(ob_child->parentinv, workob.obmat);
397                 }
398         }
399 }
400
401 static int apply_objects_internal(bContext *C, ReportList *reports, int apply_loc, int apply_scale, int apply_rot)
402 {
403         Main *bmain= CTX_data_main(C);
404         Scene *scene= CTX_data_scene(C);
405         bArmature *arm;
406         Mesh *me;
407         Curve *cu;
408         Nurb *nu;
409         BPoint *bp;
410         BezTriple *bezt;
411         MVert *mvert;
412         float rsmat[3][3], tmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
413         int a, change = 0;
414         
415         /* first check if we can execute */
416         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
417
418                 if(ob->type==OB_MESH) {
419                         me= ob->data;
420                         
421                         if(ID_REAL_USERS(me) > 1) {
422                                 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user mesh, doing nothing.");
423                                 return OPERATOR_CANCELLED;
424                         }
425                 }
426                 else if(ob->type==OB_ARMATURE) {
427                         arm= ob->data;
428                         
429                         if(ID_REAL_USERS(arm) > 1) {
430                                 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user armature, doing nothing.");
431                                 return OPERATOR_CANCELLED;
432                         }
433                 }
434                 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
435                         cu= ob->data;
436                         
437                         if(ID_REAL_USERS(cu) > 1) {
438                                 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user curve, doing nothing.");
439                                 return OPERATOR_CANCELLED;
440                         }
441                         if(!(cu->flag & CU_3D) && (apply_rot || apply_loc)) {
442                                 BKE_report(reports, RPT_ERROR, "Neither rotation nor location could be applied to a 2d curve, doing nothing.");
443                                 return OPERATOR_CANCELLED;
444                         }
445                         if(cu->key) {
446                                 BKE_report(reports, RPT_ERROR, "Can't apply to a curve with vertex keys, doing nothing.");
447                                 return OPERATOR_CANCELLED;
448                         }
449                 }
450         }
451         CTX_DATA_END;
452         
453         /* now execute */
454         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
455
456                 /* calculate rotation/scale matrix */
457                 if(apply_scale && apply_rot)
458                         object_to_mat3(ob, rsmat);
459                 else if(apply_scale)
460                         object_scale_to_mat3(ob, rsmat);
461                 else if(apply_rot) {
462                         float tmat[3][3], timat[3][3];
463
464                         /* simple rotation matrix */
465                         object_rot_to_mat3(ob, rsmat);
466
467                         /* correct for scale, note mul_m3_m3m3 has swapped args! */
468                         object_scale_to_mat3(ob, tmat);
469                         invert_m3_m3(timat, tmat);
470                         mul_m3_m3m3(rsmat, timat, rsmat);
471                         mul_m3_m3m3(rsmat, rsmat, tmat);
472                 }
473                 else
474                         unit_m3(rsmat);
475
476                 copy_m4_m3(mat, rsmat);
477
478                 /* calculate translation */
479                 if(apply_loc) {
480                         copy_v3_v3(mat[3], ob->loc);
481
482                         if(!(apply_scale && apply_rot)) {
483                                 /* correct for scale and rotation that is still applied */
484                                 object_to_mat3(ob, obmat);
485                                 invert_m3_m3(iobmat, obmat);
486                                 mul_m3_m3m3(tmat, rsmat, iobmat);
487                                 mul_m3_v3(tmat, mat[3]);
488                         }
489                 }
490
491                 /* apply to object data */
492                 if(ob->type==OB_MESH) {
493                         me= ob->data;
494                         
495                         multiresModifier_scale_disp(scene, ob);
496                         
497                         /* adjust data */
498                         mvert= me->mvert;
499                         for(a=0; a<me->totvert; a++, mvert++)
500                                 mul_m4_v3(mat, mvert->co);
501                         
502                         if(me->key) {
503                                 KeyBlock *kb;
504                                 
505                                 for(kb=me->key->block.first; kb; kb=kb->next) {
506                                         float *fp= kb->data;
507                                         
508                                         for(a=0; a<kb->totelem; a++, fp+=3)
509                                                 mul_m4_v3(mat, fp);
510                                 }
511                         }
512                         
513                         /* update normals */
514                         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
515                 }
516                 else if (ob->type==OB_ARMATURE) {
517                         ED_armature_apply_transform(ob, mat);
518                 }
519                 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
520                         cu= ob->data;
521
522                         scale = mat3_to_scale(rsmat);
523
524                         for(nu=cu->nurb.first; nu; nu=nu->next) {
525                                 if(nu->type == CU_BEZIER) {
526                                         a= nu->pntsu;
527                                         for(bezt= nu->bezt; a--; bezt++) {
528                                                 mul_m4_v3(mat, bezt->vec[0]);
529                                                 mul_m4_v3(mat, bezt->vec[1]);
530                                                 mul_m4_v3(mat, bezt->vec[2]);
531                                                 bezt->radius *= scale;
532                                         }
533                                 }
534                                 else {
535                                         a= nu->pntsu*nu->pntsv;
536                                         for(bp= nu->bp; a--; bp++)
537                                                 mul_m4_v3(mat, bp->vec);
538                                 }
539                         }
540                 }
541                 else
542                         continue;
543
544                 if(apply_loc)
545                         ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0f;
546                 if(apply_scale)
547                         ob->size[0]= ob->size[1]= ob->size[2]= 1.0f;
548                 if(apply_rot) {
549                         ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0f;
550                         ob->quat[1]= ob->quat[2]= ob->quat[3]= 0.0f;
551                         ob->rotAxis[0]= ob->rotAxis[2]= 0.0f;
552                         ob->rotAngle= 0.0f;
553                         
554                         ob->quat[0]= ob->rotAxis[1]= 1.0f;
555                 }
556
557                 where_is_object(scene, ob);
558                 ignore_parent_tx(bmain, scene, ob);
559
560                 DAG_id_flush_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA);
561
562                 change = 1;
563         }
564         CTX_DATA_END;
565
566         if(!change)
567                 return OPERATOR_CANCELLED;
568
569         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
570         return OPERATOR_FINISHED;
571 }
572
573 static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
574 {
575         Scene *scene= CTX_data_scene(C);
576         int change = 0;
577         
578         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
579                 where_is_object(scene, ob);
580                 object_apply_mat4(ob, ob->obmat, TRUE, TRUE);
581                 where_is_object(scene, ob);
582
583                 /* update for any children that may get moved */
584                 DAG_id_flush_update(&ob->id, OB_RECALC_OB);
585         
586                 change = 1;
587         }
588         CTX_DATA_END;
589
590         if(!change)
591                 return OPERATOR_CANCELLED;
592
593         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
594         return OPERATOR_FINISHED;
595 }
596
597 void OBJECT_OT_visual_transform_apply(wmOperatorType *ot)
598 {
599         /* identifiers */
600         ot->name= "Apply Visual Transform";
601         ot->description = "Apply the object's visual transformation to its data";
602         ot->idname= "OBJECT_OT_visual_transform_apply";
603         
604         /* api callbacks */
605         ot->exec= visual_transform_apply_exec;
606         ot->poll= ED_operator_scene_editable;
607         
608         /* flags */
609         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
610 }
611
612 static int location_apply_exec(bContext *C, wmOperator *op)
613 {
614         return apply_objects_internal(C, op->reports, 1, 0, 0);
615 }
616
617 void OBJECT_OT_location_apply(wmOperatorType *ot)
618 {
619         /* identifiers */
620         ot->name= "Apply Location";
621         ot->description = "Apply the object's location to its data";
622         ot->idname= "OBJECT_OT_location_apply";
623         
624         /* api callbacks */
625         ot->exec= location_apply_exec;
626         ot->poll= ED_operator_scene_editable;
627         
628         /* flags */
629         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
630 }
631
632 static int scale_apply_exec(bContext *C, wmOperator *op)
633 {
634         return apply_objects_internal(C, op->reports, 0, 1, 0);
635 }
636
637 void OBJECT_OT_scale_apply(wmOperatorType *ot)
638 {
639         /* identifiers */
640         ot->name= "Apply Scale";
641         ot->description = "Apply the object's scale to its data";
642         ot->idname= "OBJECT_OT_scale_apply";
643         
644         /* api callbacks */
645         ot->exec= scale_apply_exec;
646         ot->poll= ED_operator_scene_editable;
647         
648         /* flags */
649         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
650 }
651
652 static int rotation_apply_exec(bContext *C, wmOperator *op)
653 {
654         return apply_objects_internal(C, op->reports, 0, 0, 1);
655 }
656
657 void OBJECT_OT_rotation_apply(wmOperatorType *ot)
658 {
659         /* identifiers */
660         ot->name= "Apply Rotation";
661         ot->description = "Apply the object's rotation to its data";
662         ot->idname= "OBJECT_OT_rotation_apply";
663         
664         /* api callbacks */
665         ot->exec= rotation_apply_exec;
666         ot->poll= ED_operator_scene_editable;
667         
668         /* flags */
669         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
670 }
671
672 /************************ Texture Space Transform ****************************/
673
674 void texspace_edit(Scene *scene, View3D *v3d)
675 {
676         Base *base;
677         int nr=0;
678         
679         /* first test if from visible and selected objects
680          * texspacedraw is set:
681          */
682         
683         if(scene->obedit) return; // XXX get from context
684         
685         for(base= FIRSTBASE; base; base= base->next) {
686                 if(TESTBASELIB(v3d, base)) {
687                         break;
688                 }
689         }
690
691         if(base==0) {
692                 return;
693         }
694         
695         nr= 0; // XXX pupmenu("Texture Space %t|Grab/Move%x1|Size%x2");
696         if(nr<1) return;
697         
698         for(base= FIRSTBASE; base; base= base->next) {
699                 if(TESTBASELIB(v3d, base)) {
700                         base->object->dtx |= OB_TEXSPACE;
701                 }
702         }
703         
704
705         if(nr==1) {
706 // XXX          initTransform(TFM_TRANSLATION, CTX_TEXTURE);
707 // XXX          Transform();
708         }
709         else if(nr==2) {
710 // XXX          initTransform(TFM_RESIZE, CTX_TEXTURE);
711 // XXX          Transform();
712         }
713         else if(nr==3) {
714 // XXX          initTransform(TFM_ROTATION, CTX_TEXTURE);
715 // XXX          Transform();
716         }
717 }
718
719 /********************* Set Object Center ************************/
720
721 enum {
722         GEOMETRY_TO_ORIGIN=0,
723         ORIGIN_TO_GEOMETRY,
724         ORIGIN_TO_CURSOR
725 };
726
727 static int object_origin_set_exec(bContext *C, wmOperator *op)
728 {
729         Main *bmain= CTX_data_main(C);
730         Scene *scene= CTX_data_scene(C);
731         Object *obedit= CTX_data_edit_object(C);
732         Object *tob;
733         float cursor[3], cent[3], cent_neg[3], centn[3], min[3], max[3];
734         int centermode = RNA_enum_get(op->ptr, "type");
735         int around = RNA_enum_get(op->ptr, "center"); /* initialized from v3d->around */
736
737         /* keep track of what is changed */
738         int tot_change=0, tot_lib_error=0, tot_multiuser_arm_error=0;
739
740         if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
741                 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
742                 return OPERATOR_CANCELLED;
743         }
744         else {
745                 /* get the view settings if 'around' isnt set and the view is available */
746                 View3D *v3d= CTX_wm_view3d(C);
747                 copy_v3_v3(cursor, give_cursor(scene, v3d));
748                 if(v3d && !RNA_property_is_set(op->ptr, "around"))
749                         around= v3d->around;
750         }
751
752         zero_v3(cent);
753
754         if(obedit) {
755                 INIT_MINMAX(min, max);
756
757                 if(obedit->type==OB_MESH) {
758                         Mesh *me= obedit->data;
759                         EditMesh *em = BKE_mesh_get_editmesh(me);
760                         EditVert *eve;
761
762                         if(around==V3D_CENTROID) {
763                                 int total= 0;
764                                 for(eve= em->verts.first; eve; eve= eve->next) {
765                                         total++;
766                                         add_v3_v3(cent, eve->co);
767                                 }
768                                 mul_v3_fl(cent, 1.0f/(float)total);
769                         }
770                         else {
771                                 for(eve= em->verts.first; eve; eve= eve->next) {
772                                         DO_MINMAX(eve->co, min, max);
773                                 }
774                                 mid_v3_v3v3(cent, min, max);
775                         }
776
777                         for(eve= em->verts.first; eve; eve= eve->next) {
778                                 sub_v3_v3(eve->co, cent);
779                         }
780
781                         recalc_editnormals(em);
782                         tot_change++;
783                         DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
784                         BKE_mesh_end_editmesh(me, em);
785                 }
786         }
787
788         /* reset flags */
789         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
790                         ob->flag &= ~OB_DONE;
791         }
792         CTX_DATA_END;
793
794         for (tob= bmain->object.first; tob; tob= tob->id.next) {
795                 if(tob->data)
796                         ((ID *)tob->data)->flag &= ~LIB_DOIT;
797                 if(tob->dup_group)
798                         ((ID *)tob->dup_group)->flag &= ~LIB_DOIT;
799         }
800
801         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
802                 if((ob->flag & OB_DONE)==0) {
803                         int do_inverse_offset = FALSE;
804                         ob->flag |= OB_DONE;
805
806                         if(centermode == ORIGIN_TO_CURSOR) {
807                                 copy_v3_v3(cent, cursor);
808                                 invert_m4_m4(ob->imat, ob->obmat);
809                                 mul_m4_v3(ob->imat, cent);
810                         }
811                         
812                         if(ob->data == NULL) {
813                                 /* special support for dupligroups */
814                                 if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group && (ob->dup_group->id.flag & LIB_DOIT)==0) {
815                                         if(ob->dup_group->id.lib) {
816                                                 tot_lib_error++;
817                                         }
818                                         else {
819                                                 if(centermode == ORIGIN_TO_CURSOR) { /* done */ }
820                                                 else {
821                                                         /* only bounds support */
822                                                         INIT_MINMAX(min, max);
823                                                         minmax_object_duplis(scene, ob, min, max);
824                                                         mid_v3_v3v3(cent, min, max);
825                                                         invert_m4_m4(ob->imat, ob->obmat);
826                                                         mul_m4_v3(ob->imat, cent);
827                                                 }
828                                                 
829                                                 add_v3_v3(ob->dup_group->dupli_ofs, cent);
830
831                                                 tot_change++;
832                                                 ob->dup_group->id.flag |= LIB_DOIT;
833                                                 do_inverse_offset= TRUE;
834                                         }
835                                 }
836                         }
837                         else if (((ID *)ob->data)->lib) {
838                                 tot_lib_error++;
839                         }
840
841                         if(obedit==NULL && ob->type==OB_MESH) {
842                                 Mesh *me= ob->data;
843
844                                 if(centermode == ORIGIN_TO_CURSOR) { /* done */ }
845                                 else if(around==V3D_CENTROID) { mesh_center_median(me, cent); }
846                                 else { mesh_center_bounds(me, cent); }
847
848                                 negate_v3_v3(cent_neg, cent);
849                                 mesh_translate(me, cent_neg, 1);
850
851                                 tot_change++;
852                                 me->id.flag |= LIB_DOIT;
853                                 do_inverse_offset= TRUE;
854                         }
855                         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
856                                 Curve *cu= ob->data;
857
858                                 if(centermode == ORIGIN_TO_CURSOR) { /* done */ }
859                                 else if(around==V3D_CENTROID) { curve_center_median(cu, cent); }
860                                 else { curve_center_bounds(cu, cent);   }
861
862                                 /* don't allow Z change if curve is 2D */
863                                 if((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
864                                         cent[2] = 0.0;
865
866                                 negate_v3_v3(cent_neg, cent);
867                                 curve_translate(cu, cent_neg, 1);
868
869                                 tot_change++;
870                                 cu->id.flag |= LIB_DOIT;
871                                 do_inverse_offset= TRUE;
872
873                                 if(obedit) {
874                                         if (centermode == GEOMETRY_TO_ORIGIN) {
875                                                 DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
876                                         }
877                                         break;
878                                 }
879                         }
880                         else if(ob->type==OB_FONT) {
881                                 /* get from bb */
882
883                                 Curve *cu= ob->data;
884
885                                 if(cu->bb==NULL && (centermode != ORIGIN_TO_CURSOR)) {
886                                         /* do nothing*/
887                                 }
888                                 else {
889                                         if(centermode == ORIGIN_TO_CURSOR) {
890                                                 /* done */
891                                         }
892                                         else {
893                                                 cent[0]= 0.5f * ( cu->bb->vec[4][0] + cu->bb->vec[0][0]);
894                                                 cent[1]= 0.5f * ( cu->bb->vec[0][1] + cu->bb->vec[2][1]) - 0.5f;        /* extra 0.5 is the height o above line */
895                                         }
896
897                                         cent[2]= 0.0f;
898
899                                         cu->xof= cu->xof - (cent[0] / cu->fsize);
900                                         cu->yof= cu->yof - (cent[1] / cu->fsize);
901
902                                         tot_change++;
903                                         cu->id.flag |= LIB_DOIT;
904                                         do_inverse_offset= TRUE;
905                                 }
906                         }
907                         else if(ob->type==OB_ARMATURE) {
908                                 bArmature *arm = ob->data;
909
910                                 if(ID_REAL_USERS(arm) > 1) {
911                                         /*BKE_report(op->reports, RPT_ERROR, "Can't apply to a multi user armature");
912                                         return;*/
913                                         tot_multiuser_arm_error++;
914                                 }
915                                 else {
916                                         /* Function to recenter armatures in editarmature.c
917                                          * Bone + object locations are handled there.
918                                          */
919                                         docenter_armature(scene, ob, cursor, centermode, around);
920
921                                         tot_change++;
922                                         arm->id.flag |= LIB_DOIT;
923                                         /* do_inverse_offset= TRUE; */ /* docenter_armature() handles this */
924
925                                         where_is_object(scene, ob);
926                                         ignore_parent_tx(bmain, scene, ob);
927
928                                         if(obedit)
929                                                 break;
930                                 }
931                         }
932
933                         /* offset other selected objects */
934                         if(do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
935                                 /* was the object data modified
936                                  * note: the functions above must set 'cent' */
937                                 copy_v3_v3(centn, cent);
938                                 mul_mat3_m4_v3(ob->obmat, centn); /* ommit translation part */
939                                 add_v3_v3(ob->loc, centn);
940
941                                 where_is_object(scene, ob);
942                                 ignore_parent_tx(bmain, scene, ob);
943                                 
944                                 /* other users? */
945                                 CTX_DATA_BEGIN(C, Object*, ob_other, selected_editable_objects) {
946                                         if(             (ob_other->flag & OB_DONE)==0 &&
947                                                         (       (ob->data && (ob->data == ob_other->data)) ||
948                                                                 (ob->dup_group==ob_other->dup_group && (ob->transflag|ob_other->transflag) & OB_DUPLIGROUP) )
949                                         ) {
950                                                 ob_other->flag |= OB_DONE;
951                                                 ob_other->recalc= OB_RECALC_OB|OB_RECALC_DATA;
952
953                                                 copy_v3_v3(centn, cent);
954                                                 mul_mat3_m4_v3(ob_other->obmat, centn); /* ommit translation part */
955                                                 add_v3_v3(ob_other->loc, centn);
956
957                                                 where_is_object(scene, ob_other);
958                                                 ignore_parent_tx(bmain, scene, ob_other);
959                                         }
960                                 }
961                                 CTX_DATA_END;
962                         }
963                 }
964         }
965         CTX_DATA_END;
966
967         for (tob= bmain->object.first; tob; tob= tob->id.next) {
968                 if(tob->data && (((ID *)tob->data)->flag & LIB_DOIT)) {
969                         tob->recalc= OB_RECALC_OB|OB_RECALC_DATA;
970                 }
971         }
972
973         if (tot_change) {
974                 DAG_ids_flush_update(bmain, 0);
975                 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
976         }
977
978         /* Warn if any errors occurred */
979         if (tot_lib_error+tot_multiuser_arm_error) {
980                 BKE_reportf(op->reports, RPT_WARNING, "%i Object(s) Not Centered, %i Changed:",tot_lib_error+tot_multiuser_arm_error, tot_change);
981                 if (tot_lib_error)
982                         BKE_reportf(op->reports, RPT_WARNING, "|%i linked library objects",tot_lib_error);
983                 if (tot_multiuser_arm_error)
984                         BKE_reportf(op->reports, RPT_WARNING, "|%i multiuser armature object(s)",tot_multiuser_arm_error);
985         }
986
987         return OPERATOR_FINISHED;
988 }
989
990 void OBJECT_OT_origin_set(wmOperatorType *ot)
991 {
992         static EnumPropertyItem prop_set_center_types[] = {
993                 {GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"},
994                 {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry", "Move object origin to center of object geometry"},
995                 {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor", "Move object origin to position of the 3d cursor"},
996                 {0, NULL, 0, NULL, NULL}
997         };
998         
999         static EnumPropertyItem prop_set_bounds_types[] = {
1000                 {V3D_CENTROID, "MEDIAN", 0, "Median Center", ""},
1001                 {V3D_CENTER, "BOUNDS", 0, "Bounds Center", ""},
1002                 {0, NULL, 0, NULL, NULL}
1003         };
1004         
1005         /* identifiers */
1006         ot->name= "Set Origin";
1007         ot->description = "Set the object's origin, by either moving the data, or set to center of data, or use 3d cursor";
1008         ot->idname= "OBJECT_OT_origin_set";
1009         
1010         /* api callbacks */
1011         ot->invoke= WM_menu_invoke;
1012         ot->exec= object_origin_set_exec;
1013         
1014         ot->poll= ED_operator_scene_editable;
1015         
1016         /* flags */
1017         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1018         
1019         ot->prop= RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
1020         RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_CENTROID, "Center", "");
1021 }
1022