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