style cleanup: format 'for' loop macros the same as for loops, some renaming to BLI_a...
[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
61 #include "RNA_define.h"
62 #include "RNA_access.h"
63
64 #include "WM_api.h"
65 #include "WM_types.h"
66
67 #include "ED_armature.h"
68 #include "ED_keyframing.h"
69 #include "ED_mesh.h"
70 #include "ED_screen.h"
71 #include "ED_view3d.h"
72
73 #include "object_intern.h"
74
75 /*************************** Clear Transformation ****************************/
76
77 /* clear location of object */
78 static void object_clear_loc(Object *ob)
79 {
80         /* clear location if not locked */
81         if ((ob->protectflag & OB_LOCK_LOCX)==0)
82                 ob->loc[0]= ob->dloc[0]= 0.0f;
83         if ((ob->protectflag & OB_LOCK_LOCY)==0)
84                 ob->loc[1]= ob->dloc[1]= 0.0f;
85         if ((ob->protectflag & OB_LOCK_LOCZ)==0)
86                 ob->loc[2]= ob->dloc[2]= 0.0f;
87 }
88
89 /* clear rotation of object */
90 static void object_clear_rot(Object *ob)
91 {
92         /* clear rotations that aren't locked */
93         if (ob->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
94                 if (ob->protectflag & OB_LOCK_ROT4D) {
95                         /* perform clamping on a component by component basis */
96                         if (ob->rotmode == ROT_MODE_AXISANGLE) {
97                                 if ((ob->protectflag & OB_LOCK_ROTW) == 0)
98                                         ob->rotAngle= ob->drotAngle= 0.0f;
99                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0)
100                                         ob->rotAxis[0]= ob->drotAxis[0]= 0.0f;
101                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0)
102                                         ob->rotAxis[1]= ob->drotAxis[1]= 0.0f;
103                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0)
104                                         ob->rotAxis[2]= ob->drotAxis[2]= 0.0f;
105                                         
106                                 /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
107                                 if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2]))
108                                         ob->rotAxis[1] = 1.0f;
109                                 if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]))
110                                         ob->drotAxis[1]= 1.0f;
111                         }
112                         else if (ob->rotmode == ROT_MODE_QUAT) {
113                                 if ((ob->protectflag & OB_LOCK_ROTW) == 0)
114                                         ob->quat[0]= ob->dquat[0]= 1.0f;
115                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0)
116                                         ob->quat[1]= ob->dquat[1]= 0.0f;
117                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0)
118                                         ob->quat[2]= ob->dquat[2]= 0.0f;
119                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0)
120                                         ob->quat[3]= ob->dquat[3]= 0.0f;
121                                         
122                                 // TODO: does this quat need normalizing now?
123                         }
124                         else {
125                                 /* the flag may have been set for the other modes, so just ignore the extra flag... */
126                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0)
127                                         ob->rot[0]= ob->drot[0]= 0.0f;
128                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0)
129                                         ob->rot[1]= ob->drot[1]= 0.0f;
130                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0)
131                                         ob->rot[2]= ob->drot[2]= 0.0f;
132                         }
133                 }
134                 else {
135                         /* perform clamping using euler form (3-components) */
136                         // FIXME: deltas are not handled for these cases yet...
137                         float eul[3], oldeul[3], quat1[4] = {0};
138                         
139                         if (ob->rotmode == ROT_MODE_QUAT) {
140                                 copy_qt_qt(quat1, ob->quat);
141                                 quat_to_eul(oldeul, ob->quat);
142                         }
143                         else if (ob->rotmode == ROT_MODE_AXISANGLE) {
144                                 axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle);
145                         }
146                         else {
147                                 copy_v3_v3(oldeul, ob->rot);
148                         }
149                         
150                         eul[0]= eul[1]= eul[2]= 0.0f;
151                         
152                         if (ob->protectflag & OB_LOCK_ROTX)
153                                 eul[0]= oldeul[0];
154                         if (ob->protectflag & OB_LOCK_ROTY)
155                                 eul[1]= oldeul[1];
156                         if (ob->protectflag & OB_LOCK_ROTZ)
157                                 eul[2]= oldeul[2];
158                         
159                         if (ob->rotmode == ROT_MODE_QUAT) {
160                                 eul_to_quat(ob->quat, eul);
161                                 /* quaternions flip w sign to accumulate rotations correctly */
162                                 if ((quat1[0]<0.0f && ob->quat[0]>0.0f) || (quat1[0]>0.0f && ob->quat[0]<0.0f)) {
163                                         mul_qt_fl(ob->quat, -1.0f);
164                                 }
165                         }
166                         else if (ob->rotmode == ROT_MODE_AXISANGLE) {
167                                 eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle,eul, EULER_ORDER_DEFAULT);
168                         }
169                         else {
170                                 copy_v3_v3(ob->rot, eul);
171                         }
172                 }
173         }                                                // Duplicated in source/blender/editors/armature/editarmature.c
174         else { 
175                 if (ob->rotmode == ROT_MODE_QUAT) {
176                         unit_qt(ob->quat);
177                         unit_qt(ob->dquat);
178                 }
179                 else if (ob->rotmode == ROT_MODE_AXISANGLE) {
180                         unit_axis_angle(ob->rotAxis, &ob->rotAngle);
181                         unit_axis_angle(ob->drotAxis, &ob->drotAngle);
182                 }
183                 else {
184                         zero_v3(ob->rot);
185                         zero_v3(ob->drot);
186                 }
187         }
188 }
189
190 /* clear scale of object */
191 static void object_clear_scale(Object *ob)
192 {
193         /* clear scale factors which are not locked */
194         if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
195                 ob->dscale[0]= 1.0f;
196                 ob->size[0]= 1.0f;
197         }
198         if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
199                 ob->dscale[1]= 1.0f;
200                 ob->size[1]= 1.0f;
201         }
202         if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
203                 ob->dscale[2]= 1.0f;
204                 ob->size[2]= 1.0f;
205         }
206 }
207
208 /* --------------- */
209
210 /* generic exec for clear-transform operators */
211 static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, 
212                 void (*clear_func)(Object*), const char default_ksName[])
213 {
214         Main *bmain = CTX_data_main(C);
215         Scene *scene= CTX_data_scene(C);
216         KeyingSet *ks;
217         
218         /* sanity checks */
219         if (ELEM(NULL, clear_func, default_ksName)) {
220                 BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform func or Keying Set Name");
221                 return OPERATOR_CANCELLED;
222         }
223         
224         /* get KeyingSet to use */
225         ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
226         
227         /* operate on selected objects only if they aren't in weight-paint mode 
228          * (so that object-transform clearing won't be applied at same time as bone-clearing)
229          */
230         CTX_DATA_BEGIN (C, Object*, ob, selected_editable_objects) {
231                 if (!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
232                         /* run provided clearing function */
233                         clear_func(ob);
234
235                         ED_autokeyframe_object(C, scene, ob, ks);
236
237                         /* tag for updates */
238                         DAG_id_tag_update(&ob->id, OB_RECALC_OB);
239                 }
240         }
241         CTX_DATA_END;
242         
243         /* this is needed so children are also updated */
244         DAG_ids_flush_update(bmain, 0);
245
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         Main *bmain= CTX_data_main(C);
319         float *v1, *v3;
320         float mat[3][3];
321
322         CTX_DATA_BEGIN (C, Object*, ob, selected_editable_objects) {
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         DAG_ids_flush_update(bmain, 0);
338         
339         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
340         
341         return OPERATOR_FINISHED;
342 }
343
344 void OBJECT_OT_origin_clear(wmOperatorType *ot)
345 {
346         /* identifiers */
347         ot->name = "Clear Origin";
348         ot->description = "Clear the object's origin";
349         ot->idname = "OBJECT_OT_origin_clear";
350         
351         /* api callbacks */
352         ot->exec = object_origin_clear_exec;
353         ot->poll = ED_operator_scene_editable;
354         
355         /* flags */
356         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
357 }
358
359 /*************************** Apply Transformation ****************************/
360
361 /* use this when the loc/size/rot of the parent has changed but the children
362  * should stay in the same place, e.g. for apply-size-rot or object center */
363 static void ignore_parent_tx(Main *bmain, Scene *scene, Object *ob ) 
364 {
365         Object workob;
366         Object *ob_child;
367         
368         /* a change was made, adjust the children to compensate */
369         for (ob_child=bmain->object.first; ob_child; ob_child=ob_child->id.next) {
370                 if (ob_child->parent == ob) {
371                         object_apply_mat4(ob_child, ob_child->obmat, TRUE, FALSE);
372                         what_does_parent(scene, ob_child, &workob);
373                         invert_m4_m4(ob_child->parentinv, workob.obmat);
374                 }
375         }
376 }
377
378 static int apply_objects_internal(bContext *C, ReportList *reports, int apply_loc, int apply_rot, int apply_scale)
379 {
380         Main *bmain= CTX_data_main(C);
381         Scene *scene= CTX_data_scene(C);
382         float rsmat[3][3], tmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
383         int a, change = 0;
384         
385         /* first check if we can execute */
386         CTX_DATA_BEGIN (C, Object*, ob, selected_editable_objects) {
387
388                 if (ob->type==OB_MESH) {
389                         if (ID_REAL_USERS(ob->data) > 1) {
390                                 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user mesh, doing nothing");
391                                 return OPERATOR_CANCELLED;
392                         }
393                 }
394                 else if (ob->type==OB_ARMATURE) {
395                         if (ID_REAL_USERS(ob->data) > 1) {
396                                 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user armature, doing nothing");
397                                 return OPERATOR_CANCELLED;
398                         }
399                 }
400                 else if (ob->type == OB_LATTICE) {
401                         if (ID_REAL_USERS(ob->data) > 1) {
402                                 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user lattice, doing nothing");
403                                 return OPERATOR_CANCELLED;
404                         }
405                 }
406                 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
407                         Curve *cu;
408
409                         if (ID_REAL_USERS(ob->data) > 1) {
410                                 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user curve, doing nothing");
411                                 return OPERATOR_CANCELLED;
412                         }
413
414                         cu= ob->data;
415
416                         if (!(cu->flag & CU_3D) && (apply_rot || apply_loc)) {
417                                 BKE_report(reports, RPT_ERROR, "Neither rotation nor location could be applied to a 2d curve, doing nothing");
418                                 return OPERATOR_CANCELLED;
419                         }
420                         if (cu->key) {
421                                 BKE_report(reports, RPT_ERROR, "Can't apply to a curve with vertex keys, doing nothing");
422                                 return OPERATOR_CANCELLED;
423                         }
424                 }
425         }
426         CTX_DATA_END;
427         
428         /* now execute */
429         CTX_DATA_BEGIN (C, Object*, ob, selected_editable_objects) {
430
431                 /* calculate rotation/scale matrix */
432                 if (apply_scale && apply_rot)
433                         object_to_mat3(ob, rsmat);
434                 else if (apply_scale)
435                         object_scale_to_mat3(ob, rsmat);
436                 else if (apply_rot) {
437                         float tmat[3][3], timat[3][3];
438
439                         /* simple rotation matrix */
440                         object_rot_to_mat3(ob, rsmat);
441
442                         /* correct for scale, note mul_m3_m3m3 has swapped args! */
443                         object_scale_to_mat3(ob, tmat);
444                         invert_m3_m3(timat, tmat);
445                         mul_m3_m3m3(rsmat, timat, rsmat);
446                         mul_m3_m3m3(rsmat, rsmat, tmat);
447                 }
448                 else
449                         unit_m3(rsmat);
450
451                 copy_m4_m3(mat, rsmat);
452
453                 /* calculate translation */
454                 if (apply_loc) {
455                         copy_v3_v3(mat[3], ob->loc);
456
457                         if (!(apply_scale && apply_rot)) {
458                                 /* correct for scale and rotation that is still applied */
459                                 object_to_mat3(ob, obmat);
460                                 invert_m3_m3(iobmat, obmat);
461                                 mul_m3_m3m3(tmat, rsmat, iobmat);
462                                 mul_m3_v3(tmat, mat[3]);
463                         }
464                 }
465
466                 /* apply to object data */
467                 if (ob->type==OB_MESH) {
468                         Mesh *me= ob->data;
469                         MVert *mvert;
470
471                         multiresModifier_scale_disp(scene, ob);
472                         
473                         /* adjust data */
474                         mvert= me->mvert;
475                         for (a=0; a<me->totvert; a++, mvert++)
476                                 mul_m4_v3(mat, mvert->co);
477                         
478                         if (me->key) {
479                                 KeyBlock *kb;
480                                 
481                                 for (kb=me->key->block.first; kb; kb=kb->next) {
482                                         float *fp= kb->data;
483                                         
484                                         for (a=0; a<kb->totelem; a++, fp+=3)
485                                                 mul_m4_v3(mat, fp);
486                                 }
487                         }
488                         
489                         /* update normals */
490                         mesh_calc_normals_mapping(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
491                 }
492                 else if (ob->type==OB_ARMATURE) {
493                         ED_armature_apply_transform(ob, mat);
494                 }
495                 else if (ob->type == OB_LATTICE) {
496                         Lattice *lt = ob->data;
497                         BPoint *bp = lt->def;
498                         int a = lt->pntsu * lt->pntsv * lt->pntsw;
499                         
500                         while (a--) {
501                                 mul_m4_v3(mat, bp->vec);
502                                 bp++;
503                         }
504                 }
505                 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
506                         Curve *cu= ob->data;
507
508                         Nurb *nu;
509                         BPoint *bp;
510                         BezTriple *bezt;
511
512                         scale = mat3_to_scale(rsmat);
513
514                         for (nu=cu->nurb.first; nu; nu=nu->next) {
515                                 if (nu->type == CU_BEZIER) {
516                                         a= nu->pntsu;
517                                         for (bezt= nu->bezt; a--; bezt++) {
518                                                 mul_m4_v3(mat, bezt->vec[0]);
519                                                 mul_m4_v3(mat, bezt->vec[1]);
520                                                 mul_m4_v3(mat, bezt->vec[2]);
521                                                 bezt->radius *= scale;
522                                         }
523                                         calchandlesNurb(nu);
524                                 }
525                                 else {
526                                         a= nu->pntsu*nu->pntsv;
527                                         for (bp= nu->bp; a--; bp++)
528                                                 mul_m4_v3(mat, bp->vec);
529                                 }
530                         }
531                 }
532                 else
533                         continue;
534
535                 if (apply_loc)
536                         zero_v3(ob->loc);
537                 if (apply_scale)
538                         ob->size[0]= ob->size[1]= ob->size[2]= 1.0f;
539                 if (apply_rot) {
540                         zero_v3(ob->rot);
541                         unit_qt(ob->quat);
542                         unit_axis_angle(ob->rotAxis, &ob->rotAngle);
543                 }
544
545                 where_is_object(scene, ob);
546                 if (ob->type==OB_ARMATURE) {
547                         where_is_pose(scene, ob); /* needed for bone parents */
548                 }
549
550                 ignore_parent_tx(bmain, scene, ob);
551
552                 DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA);
553
554                 change = 1;
555         }
556         CTX_DATA_END;
557
558         if (!change)
559                 return OPERATOR_CANCELLED;
560
561         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
562         return OPERATOR_FINISHED;
563 }
564
565 static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
566 {
567         Scene *scene= CTX_data_scene(C);
568         int change = 0;
569         
570         CTX_DATA_BEGIN (C, Object*, ob, selected_editable_objects) {
571                 where_is_object(scene, ob);
572                 object_apply_mat4(ob, ob->obmat, TRUE, TRUE);
573                 where_is_object(scene, ob);
574
575                 /* update for any children that may get moved */
576                 DAG_id_tag_update(&ob->id, OB_RECALC_OB);
577         
578                 change = 1;
579         }
580         CTX_DATA_END;
581
582         if (!change)
583                 return OPERATOR_CANCELLED;
584
585         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
586         return OPERATOR_FINISHED;
587 }
588
589 void OBJECT_OT_visual_transform_apply(wmOperatorType *ot)
590 {
591         /* identifiers */
592         ot->name = "Apply Visual Transform";
593         ot->description = "Apply the object's visual transformation to its data";
594         ot->idname = "OBJECT_OT_visual_transform_apply";
595         
596         /* api callbacks */
597         ot->exec = visual_transform_apply_exec;
598         ot->poll = ED_operator_scene_editable;
599         
600         /* flags */
601         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
602 }
603
604 static int object_transform_apply_exec(bContext *C, wmOperator *op)
605 {
606         const int loc= RNA_boolean_get(op->ptr, "location");
607         const int rot= RNA_boolean_get(op->ptr, "rotation");
608         const int sca= RNA_boolean_get(op->ptr, "scale");
609
610         if (loc || rot || sca) {
611                 return apply_objects_internal(C, op->reports, loc, rot, sca);
612         }
613         else {
614                 return OPERATOR_CANCELLED;
615         }
616 }
617
618 void OBJECT_OT_transform_apply(wmOperatorType *ot)
619 {
620         /* identifiers */
621         ot->name = "Apply Object Transform";
622         ot->description = "Apply the object's transformation to its data";
623         ot->idname = "OBJECT_OT_transform_apply";
624
625         /* api callbacks */
626         ot->exec = object_transform_apply_exec;
627         ot->poll = ED_operator_objectmode;
628
629         /* flags */
630         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
631
632         RNA_def_boolean(ot->srna, "location", 0, "Location", "");
633         RNA_def_boolean(ot->srna, "rotation", 0, "Rotation", "");
634         RNA_def_boolean(ot->srna, "scale", 0, "Scale", "");
635 }
636
637 /********************* Set Object Center ************************/
638
639 enum {
640         GEOMETRY_TO_ORIGIN=0,
641         ORIGIN_TO_GEOMETRY,
642         ORIGIN_TO_CURSOR
643 };
644
645 static int object_origin_set_exec(bContext *C, wmOperator *op)
646 {
647         Main *bmain= CTX_data_main(C);
648         Scene *scene= CTX_data_scene(C);
649         Object *obedit= CTX_data_edit_object(C);
650         Object *tob;
651         float cursor[3], cent[3], cent_neg[3], centn[3], min[3], max[3];
652         int centermode = RNA_enum_get(op->ptr, "type");
653         int around = RNA_enum_get(op->ptr, "center"); /* initialized from v3d->around */
654
655         /* keep track of what is changed */
656         int tot_change=0, tot_lib_error=0, tot_multiuser_arm_error=0;
657
658         if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
659                 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
660                 return OPERATOR_CANCELLED;
661         }
662         else {
663                 /* get the view settings if 'around' isn't set and the view is available */
664                 View3D *v3d= CTX_wm_view3d(C);
665                 copy_v3_v3(cursor, give_cursor(scene, v3d));
666                 if (v3d && !RNA_struct_property_is_set(op->ptr, "center"))
667                         around= v3d->around;
668         }
669
670         zero_v3(cent);
671
672         if (obedit) {
673                 INIT_MINMAX(min, max);
674
675                 if (obedit->type==OB_MESH) {
676                         Mesh *me= obedit->data;
677                         BMEditMesh *em = me->edit_btmesh;
678                         BMVert *eve;
679                         BMIter iter;
680                         int total = 0;
681                         
682                         if (centermode == ORIGIN_TO_CURSOR) {
683                                 copy_v3_v3(cent, cursor);
684                                 invert_m4_m4(obedit->imat, obedit->obmat);
685                                 mul_m4_v3(obedit->imat, cent);
686                         }
687                         else {
688                                 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
689                                         if (around==V3D_CENTROID) {
690                                                 total++;
691                                                 add_v3_v3(cent, eve->co);
692                                                 mul_v3_fl(cent, 1.0f/(float)total);
693                                         }
694                                         else {
695                                                 DO_MINMAX(eve->co, min, max);
696                                                 mid_v3_v3v3(cent, min, max);
697                                         }
698                                 }
699                         }
700                         
701                         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
702                                 sub_v3_v3(eve->co, cent);
703                         }
704
705                         EDBM_mesh_normals_update(em);
706                         tot_change++;
707                         DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
708             }
709         }
710
711         /* reset flags */
712         CTX_DATA_BEGIN (C, Object*, ob, selected_editable_objects) {
713                         ob->flag &= ~OB_DONE;
714         }
715         CTX_DATA_END;
716
717         for (tob= bmain->object.first; tob; tob= tob->id.next) {
718                 if (tob->data)
719                         ((ID *)tob->data)->flag &= ~LIB_DOIT;
720                 if (tob->dup_group)
721                         ((ID *)tob->dup_group)->flag &= ~LIB_DOIT;
722         }
723
724         CTX_DATA_BEGIN (C, Object*, ob, selected_editable_objects) {
725                 if ((ob->flag & OB_DONE)==0) {
726                         int do_inverse_offset = FALSE;
727                         ob->flag |= OB_DONE;
728
729                         if (centermode == ORIGIN_TO_CURSOR) {
730                                 copy_v3_v3(cent, cursor);
731                                 invert_m4_m4(ob->imat, ob->obmat);
732                                 mul_m4_v3(ob->imat, cent);
733                         }
734                         
735                         if (ob->data == NULL) {
736                                 /* special support for dupligroups */
737                                 if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group && (ob->dup_group->id.flag & LIB_DOIT)==0) {
738                                         if (ob->dup_group->id.lib) {
739                                                 tot_lib_error++;
740                                         }
741                                         else {
742                                                 if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
743                                                 else {
744                                                         /* only bounds support */
745                                                         INIT_MINMAX(min, max);
746                                                         minmax_object_duplis(scene, ob, min, max);
747                                                         mid_v3_v3v3(cent, min, max);
748                                                         invert_m4_m4(ob->imat, ob->obmat);
749                                                         mul_m4_v3(ob->imat, cent);
750                                                 }
751                                                 
752                                                 add_v3_v3(ob->dup_group->dupli_ofs, cent);
753
754                                                 tot_change++;
755                                                 ob->dup_group->id.flag |= LIB_DOIT;
756                                                 do_inverse_offset= TRUE;
757                                         }
758                                 }
759                         }
760                         else if (((ID *)ob->data)->lib) {
761                                 tot_lib_error++;
762                         }
763
764                         if (obedit==NULL && ob->type==OB_MESH) {
765                                 Mesh *me= ob->data;
766
767                                 if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
768                                 else if (around==V3D_CENTROID) { mesh_center_median(me, cent); }
769                                 else { mesh_center_bounds(me, cent); }
770
771                                 negate_v3_v3(cent_neg, cent);
772                                 mesh_translate(me, cent_neg, 1);
773
774                                 tot_change++;
775                                 me->id.flag |= LIB_DOIT;
776                                 do_inverse_offset= TRUE;
777                         }
778                         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
779                                 Curve *cu= ob->data;
780
781                                 if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
782                                 else if (around==V3D_CENTROID) { curve_center_median(cu, cent); }
783                                 else { curve_center_bounds(cu, cent);   }
784
785                                 /* don't allow Z change if curve is 2D */
786                                 if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
787                                         cent[2] = 0.0;
788
789                                 negate_v3_v3(cent_neg, cent);
790                                 curve_translate(cu, cent_neg, 1);
791
792                                 tot_change++;
793                                 cu->id.flag |= LIB_DOIT;
794                                 do_inverse_offset= TRUE;
795
796                                 if (obedit) {
797                                         if (centermode == GEOMETRY_TO_ORIGIN) {
798                                                 DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
799                                         }
800                                         break;
801                                 }
802                         }
803                         else if (ob->type==OB_FONT) {
804                                 /* get from bb */
805
806                                 Curve *cu= ob->data;
807
808                                 if (cu->bb==NULL && (centermode != ORIGIN_TO_CURSOR)) {
809                                         /* do nothing*/
810                                 }
811                                 else {
812                                         if (centermode == ORIGIN_TO_CURSOR) {
813                                                 /* done */
814                                         }
815                                         else {
816                                                 cent[0]= 0.5f * ( cu->bb->vec[4][0] + cu->bb->vec[0][0]);
817                                                 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 */
818                                         }
819
820                                         cent[2]= 0.0f;
821
822                                         cu->xof= cu->xof - (cent[0] / cu->fsize);
823                                         cu->yof= cu->yof - (cent[1] / cu->fsize);
824
825                                         tot_change++;
826                                         cu->id.flag |= LIB_DOIT;
827                                         do_inverse_offset= TRUE;
828                                 }
829                         }
830                         else if (ob->type==OB_ARMATURE) {
831                                 bArmature *arm = ob->data;
832
833                                 if (ID_REAL_USERS(arm) > 1) {
834 #if 0
835                                         BKE_report(op->reports, RPT_ERROR, "Can't apply to a multi user armature");
836                                         return;
837 #endif
838                                         tot_multiuser_arm_error++;
839                                 }
840                                 else {
841                                         /* Function to recenter armatures in editarmature.c
842                                          * Bone + object locations are handled there.
843                                          */
844                                         docenter_armature(scene, ob, cursor, centermode, around);
845
846                                         tot_change++;
847                                         arm->id.flag |= LIB_DOIT;
848                                         /* do_inverse_offset= TRUE; */ /* docenter_armature() handles this */
849
850                                         where_is_object(scene, ob);
851                                         where_is_pose(scene, ob); /* needed for bone parents */
852
853                                         ignore_parent_tx(bmain, scene, ob);
854
855                                         if (obedit)
856                                                 break;
857                                 }
858                         }
859                         else if (ob->type == OB_MBALL) {
860                                 MetaBall *mb = ob->data;
861
862                                 if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
863                                 else if (around==V3D_CENTROID) { BKE_metaball_center_median(mb, cent); }
864                                 else { BKE_metaball_center_bounds(mb, cent);    }
865
866                                 negate_v3_v3(cent_neg, cent);
867                                 BKE_metaball_translate(mb, cent_neg);
868
869                                 tot_change++;
870                                 mb->id.flag |= LIB_DOIT;
871                                 do_inverse_offset= TRUE;
872
873                                 if (obedit) {
874                                         if (centermode == GEOMETRY_TO_ORIGIN) {
875                                                 DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
876                                         }
877                                         break;
878                                 }
879                         }
880
881                         /* offset other selected objects */
882                         if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
883                                 /* was the object data modified
884                                  * note: the functions above must set 'cent' */
885                                 copy_v3_v3(centn, cent);
886                                 mul_mat3_m4_v3(ob->obmat, centn); /* ommit translation part */
887                                 add_v3_v3(ob->loc, centn);
888
889                                 where_is_object(scene, ob);
890                                 if (ob->type==OB_ARMATURE) {
891                                         where_is_pose(scene, ob); /* needed for bone parents */
892                                 }
893
894                                 ignore_parent_tx(bmain, scene, ob);
895                                 
896                                 /* other users? */
897                                 CTX_DATA_BEGIN (C, Object*, ob_other, selected_editable_objects) {
898                                         if ((ob_other->flag & OB_DONE) == 0 &&
899                                             ((ob->data && (ob->data == ob_other->data)) ||
900                                              (ob->dup_group == ob_other->dup_group &&
901                                               (ob->transflag | ob_other->transflag) & OB_DUPLIGROUP)))
902                                         {
903                                                 ob_other->flag |= OB_DONE;
904                                                 DAG_id_tag_update(&ob_other->id, OB_RECALC_OB|OB_RECALC_DATA);
905
906                                                 copy_v3_v3(centn, cent);
907                                                 mul_mat3_m4_v3(ob_other->obmat, centn); /* ommit translation part */
908                                                 add_v3_v3(ob_other->loc, centn);
909
910                                                 where_is_object(scene, ob_other);
911                                                 if (ob_other->type==OB_ARMATURE) {
912                                                         where_is_pose(scene, ob_other); /* needed for bone parents */
913                                                 }
914                                                 ignore_parent_tx(bmain, scene, ob_other);
915                                         }
916                                 }
917                                 CTX_DATA_END;
918                         }
919                 }
920         }
921         CTX_DATA_END;
922
923         for (tob= bmain->object.first; tob; tob= tob->id.next)
924                 if (tob->data && (((ID *)tob->data)->flag & LIB_DOIT))
925                         DAG_id_tag_update(&tob->id, OB_RECALC_OB|OB_RECALC_DATA);
926
927         if (tot_change) {
928                 DAG_ids_flush_update(bmain, 0);
929                 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
930         }
931
932         /* Warn if any errors occurred */
933         if (tot_lib_error+tot_multiuser_arm_error) {
934                 BKE_reportf(op->reports, RPT_WARNING, "%i Object(s) Not Centered, %i Changed:",tot_lib_error+tot_multiuser_arm_error, tot_change);
935                 if (tot_lib_error)
936                         BKE_reportf(op->reports, RPT_WARNING, "|%i linked library objects",tot_lib_error);
937                 if (tot_multiuser_arm_error)
938                         BKE_reportf(op->reports, RPT_WARNING, "|%i multiuser armature object(s)",tot_multiuser_arm_error);
939         }
940
941         return OPERATOR_FINISHED;
942 }
943
944 void OBJECT_OT_origin_set(wmOperatorType *ot)
945 {
946         static EnumPropertyItem prop_set_center_types[] = {
947                 {GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"},
948                 {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry", "Move object origin to center of object geometry"},
949                 {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor", "Move object origin to position of the 3d cursor"},
950                 {0, NULL, 0, NULL, NULL}
951         };
952         
953         static EnumPropertyItem prop_set_bounds_types[] = {
954                 {V3D_CENTROID, "MEDIAN", 0, "Median Center", ""},
955                 {V3D_CENTER, "BOUNDS", 0, "Bounds Center", ""},
956                 {0, NULL, 0, NULL, NULL}
957         };
958         
959         /* identifiers */
960         ot->name = "Set Origin";
961         ot->description = "Set the object's origin, by either moving the data, or set to center of data, or use 3d cursor";
962         ot->idname = "OBJECT_OT_origin_set";
963         
964         /* api callbacks */
965         ot->invoke = WM_menu_invoke;
966         ot->exec = object_origin_set_exec;
967         
968         ot->poll = ED_operator_scene_editable;
969         
970         /* flags */
971         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
972         
973         ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
974         RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_CENTROID, "Center", "");
975 }
976