Cleanup: replace attrib w/ attr
[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_mesh_types.h"
37 #include "DNA_meta_types.h"
38 #include "DNA_lamp_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_gpencil_types.h"
42 #include "DNA_collection_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 #include "BLI_array.h"
49
50 #include "BKE_context.h"
51 #include "BKE_curve.h"
52 #include "BKE_main.h"
53 #include "BKE_idcode.h"
54 #include "BKE_mball.h"
55 #include "BKE_mesh.h"
56 #include "BKE_object.h"
57 #include "BKE_report.h"
58 #include "BKE_editmesh.h"
59 #include "BKE_multires.h"
60 #include "BKE_armature.h"
61 #include "BKE_lattice.h"
62 #include "BKE_tracking.h"
63 #include "BKE_gpencil.h"
64
65 #include "DEG_depsgraph.h"
66
67 #include "RNA_define.h"
68 #include "RNA_access.h"
69
70 #include "WM_api.h"
71 #include "WM_types.h"
72
73 #include "ED_armature.h"
74 #include "ED_keyframing.h"
75 #include "ED_mesh.h"
76 #include "ED_screen.h"
77 #include "ED_view3d.h"
78 #include "ED_gpencil.h"
79
80 #include "MEM_guardedalloc.h"
81
82 #include "object_intern.h"
83
84 /*************************** Clear Transformation ****************************/
85
86 /* clear location of object */
87 static void object_clear_loc(Object *ob, const bool clear_delta)
88 {
89         /* clear location if not locked */
90         if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
91                 ob->loc[0] = 0.0f;
92                 if (clear_delta) ob->dloc[0] = 0.0f;
93         }
94         if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
95                 ob->loc[1] = 0.0f;
96                 if (clear_delta) ob->dloc[1] = 0.0f;
97         }
98         if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
99                 ob->loc[2] = 0.0f;
100                 if (clear_delta) ob->dloc[2] = 0.0f;
101         }
102 }
103
104 /* clear rotation of object */
105 static void object_clear_rot(Object *ob, const bool clear_delta)
106 {
107         /* clear rotations that aren't locked */
108         if (ob->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
109                 if (ob->protectflag & OB_LOCK_ROT4D) {
110                         /* perform clamping on a component by component basis */
111                         if (ob->rotmode == ROT_MODE_AXISANGLE) {
112                                 if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
113                                         ob->rotAngle = 0.0f;
114                                         if (clear_delta) ob->drotAngle = 0.0f;
115                                 }
116                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
117                                         ob->rotAxis[0] = 0.0f;
118                                         if (clear_delta) ob->drotAxis[0] = 0.0f;
119                                 }
120                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
121                                         ob->rotAxis[1] = 0.0f;
122                                         if (clear_delta) ob->drotAxis[1] = 0.0f;
123                                 }
124                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
125                                         ob->rotAxis[2] = 0.0f;
126                                         if (clear_delta) ob->drotAxis[2] = 0.0f;
127                                 }
128
129                                 /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
130                                 if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2]))
131                                         ob->rotAxis[1] = 1.0f;
132                                 if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]) && clear_delta)
133                                         ob->drotAxis[1] = 1.0f;
134                         }
135                         else if (ob->rotmode == ROT_MODE_QUAT) {
136                                 if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
137                                         ob->quat[0] = 1.0f;
138                                         if (clear_delta) ob->dquat[0] = 1.0f;
139                                 }
140                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
141                                         ob->quat[1] = 0.0f;
142                                         if (clear_delta) ob->dquat[1] = 0.0f;
143                                 }
144                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
145                                         ob->quat[2] = 0.0f;
146                                         if (clear_delta) ob->dquat[2] = 0.0f;
147                                 }
148                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
149                                         ob->quat[3] = 0.0f;
150                                         if (clear_delta) ob->dquat[3] = 0.0f;
151                                 }
152                                 /* TODO: does this quat need normalizing now? */
153                         }
154                         else {
155                                 /* the flag may have been set for the other modes, so just ignore the extra flag... */
156                                 if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
157                                         ob->rot[0] = 0.0f;
158                                         if (clear_delta) ob->drot[0] = 0.0f;
159                                 }
160                                 if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
161                                         ob->rot[1] = 0.0f;
162                                         if (clear_delta) ob->drot[1] = 0.0f;
163                                 }
164                                 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
165                                         ob->rot[2] = 0.0f;
166                                         if (clear_delta) ob->drot[2] = 0.0f;
167                                 }
168                         }
169                 }
170                 else {
171                         /* perform clamping using euler form (3-components) */
172                         /* FIXME: deltas are not handled for these cases yet... */
173                         float eul[3], oldeul[3], quat1[4] = {0};
174
175                         if (ob->rotmode == ROT_MODE_QUAT) {
176                                 copy_qt_qt(quat1, ob->quat);
177                                 quat_to_eul(oldeul, ob->quat);
178                         }
179                         else if (ob->rotmode == ROT_MODE_AXISANGLE) {
180                                 axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle);
181                         }
182                         else {
183                                 copy_v3_v3(oldeul, ob->rot);
184                         }
185
186                         eul[0] = eul[1] = eul[2] = 0.0f;
187
188                         if (ob->protectflag & OB_LOCK_ROTX)
189                                 eul[0] = oldeul[0];
190                         if (ob->protectflag & OB_LOCK_ROTY)
191                                 eul[1] = oldeul[1];
192                         if (ob->protectflag & OB_LOCK_ROTZ)
193                                 eul[2] = oldeul[2];
194
195                         if (ob->rotmode == ROT_MODE_QUAT) {
196                                 eul_to_quat(ob->quat, eul);
197                                 /* quaternions flip w sign to accumulate rotations correctly */
198                                 if ((quat1[0] < 0.0f && ob->quat[0] > 0.0f) || (quat1[0] > 0.0f && ob->quat[0] < 0.0f)) {
199                                         mul_qt_fl(ob->quat, -1.0f);
200                                 }
201                         }
202                         else if (ob->rotmode == ROT_MODE_AXISANGLE) {
203                                 eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle, eul, EULER_ORDER_DEFAULT);
204                         }
205                         else {
206                                 copy_v3_v3(ob->rot, eul);
207                         }
208                 }
209         }                        // Duplicated in source/blender/editors/armature/editarmature.c
210         else {
211                 if (ob->rotmode == ROT_MODE_QUAT) {
212                         unit_qt(ob->quat);
213                         if (clear_delta) unit_qt(ob->dquat);
214                 }
215                 else if (ob->rotmode == ROT_MODE_AXISANGLE) {
216                         unit_axis_angle(ob->rotAxis, &ob->rotAngle);
217                         if (clear_delta) unit_axis_angle(ob->drotAxis, &ob->drotAngle);
218                 }
219                 else {
220                         zero_v3(ob->rot);
221                         if (clear_delta) zero_v3(ob->drot);
222                 }
223         }
224 }
225
226 /* clear scale of object */
227 static void object_clear_scale(Object *ob, const bool clear_delta)
228 {
229         /* clear scale factors which are not locked */
230         if ((ob->protectflag & OB_LOCK_SCALEX) == 0) {
231                 ob->size[0] = 1.0f;
232                 if (clear_delta) ob->dscale[0] = 1.0f;
233         }
234         if ((ob->protectflag & OB_LOCK_SCALEY) == 0) {
235                 ob->size[1] = 1.0f;
236                 if (clear_delta) ob->dscale[1] = 1.0f;
237         }
238         if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) {
239                 ob->size[2] = 1.0f;
240                 if (clear_delta) ob->dscale[2] = 1.0f;
241         }
242 }
243
244 /* --------------- */
245
246 /* generic exec for clear-transform operators */
247 static int object_clear_transform_generic_exec(bContext *C, wmOperator *op,
248                                                void (*clear_func)(Object *, const bool),
249                                                const char default_ksName[])
250 {
251         Scene *scene = CTX_data_scene(C);
252         KeyingSet *ks;
253         const bool clear_delta = RNA_boolean_get(op->ptr, "clear_delta");
254
255         /* sanity checks */
256         if (ELEM(NULL, clear_func, default_ksName)) {
257                 BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform function or keying set name");
258                 return OPERATOR_CANCELLED;
259         }
260
261         /* get KeyingSet to use */
262         ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
263
264         /* operate on selected objects only if they aren't in weight-paint mode
265          * (so that object-transform clearing won't be applied at same time as bone-clearing)
266          */
267         CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
268         {
269                 if (!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
270                         /* run provided clearing function */
271                         clear_func(ob, clear_delta);
272
273                         ED_autokeyframe_object(C, scene, ob, ks);
274
275                         /* tag for updates */
276                         DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
277                 }
278         }
279         CTX_DATA_END;
280
281         /* this is needed so children are also updated */
282         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
283
284         return OPERATOR_FINISHED;
285 }
286
287 /* --------------- */
288
289
290 static int object_location_clear_exec(bContext *C, wmOperator *op)
291 {
292         return object_clear_transform_generic_exec(C, op, object_clear_loc, ANIM_KS_LOCATION_ID);
293 }
294
295 void OBJECT_OT_location_clear(wmOperatorType *ot)
296 {
297         /* identifiers */
298         ot->name = "Clear Location";
299         ot->description = "Clear the object's location";
300         ot->idname = "OBJECT_OT_location_clear";
301
302         /* api callbacks */
303         ot->exec = object_location_clear_exec;
304         ot->poll = ED_operator_scene_editable;
305
306         /* flags */
307         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
308
309
310         /* properties */
311         ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
312                                    "Clear delta location in addition to clearing the normal location transform");
313 }
314
315 static int object_rotation_clear_exec(bContext *C, wmOperator *op)
316 {
317         return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID);
318 }
319
320 void OBJECT_OT_rotation_clear(wmOperatorType *ot)
321 {
322         /* identifiers */
323         ot->name = "Clear Rotation";
324         ot->description = "Clear the object's rotation";
325         ot->idname = "OBJECT_OT_rotation_clear";
326
327         /* api callbacks */
328         ot->exec = object_rotation_clear_exec;
329         ot->poll = ED_operator_scene_editable;
330
331         /* flags */
332         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
333
334         /* properties */
335         ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
336                                    "Clear delta rotation in addition to clearing the normal rotation transform");
337 }
338
339 static int object_scale_clear_exec(bContext *C, wmOperator *op)
340 {
341         return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID);
342 }
343
344 void OBJECT_OT_scale_clear(wmOperatorType *ot)
345 {
346         /* identifiers */
347         ot->name = "Clear Scale";
348         ot->description = "Clear the object's scale";
349         ot->idname = "OBJECT_OT_scale_clear";
350
351         /* api callbacks */
352         ot->exec = object_scale_clear_exec;
353         ot->poll = ED_operator_scene_editable;
354
355         /* flags */
356         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
357
358         /* properties */
359         ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
360                                    "Clear delta scale in addition to clearing the normal scale transform");
361 }
362
363 /* --------------- */
364
365 static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
366 {
367         float *v1, *v3;
368         float mat[3][3];
369
370         CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
371         {
372                 if (ob->parent) {
373                         /* vectors pointed to by v1 and v3 will get modified */
374                         v1 = ob->loc;
375                         v3 = ob->parentinv[3];
376
377                         copy_m3_m4(mat, ob->parentinv);
378                         negate_v3_v3(v3, v1);
379                         mul_m3_v3(mat, v3);
380                 }
381
382                 DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
383         }
384         CTX_DATA_END;
385
386         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
387
388         return OPERATOR_FINISHED;
389 }
390
391 void OBJECT_OT_origin_clear(wmOperatorType *ot)
392 {
393         /* identifiers */
394         ot->name = "Clear Origin";
395         ot->description = "Clear the object's origin";
396         ot->idname = "OBJECT_OT_origin_clear";
397
398         /* api callbacks */
399         ot->exec = object_origin_clear_exec;
400         ot->poll = ED_operator_scene_editable;
401
402         /* flags */
403         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
404 }
405
406 /*************************** Apply Transformation ****************************/
407
408 /* use this when the loc/size/rot of the parent has changed but the children
409  * should stay in the same place, e.g. for apply-size-rot or object center */
410 static void ignore_parent_tx(const bContext *C, Main *bmain, Scene *scene, Object *ob)
411 {
412         Object workob;
413         Object *ob_child;
414         Depsgraph *depsgraph = CTX_data_depsgraph(C);
415
416         /* a change was made, adjust the children to compensate */
417         for (ob_child = bmain->object.first; ob_child; ob_child = ob_child->id.next) {
418                 if (ob_child->parent == ob) {
419                         BKE_object_apply_mat4(ob_child, ob_child->obmat, true, false);
420                         BKE_object_workob_calc_parent(depsgraph, scene, ob_child, &workob);
421                         invert_m4_m4(ob_child->parentinv, workob.obmat);
422                 }
423         }
424 }
425
426 static int apply_objects_internal(
427         bContext *C, ReportList *reports,
428         bool apply_loc, bool apply_rot, bool apply_scale,
429         bool do_props)
430 {
431         Main *bmain = CTX_data_main(C);
432         Scene *scene = CTX_data_scene(C);
433         Depsgraph *depsgraph = CTX_data_depsgraph(C);
434         float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
435         bool changed = true;
436
437         /* first check if we can execute */
438         CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
439         {
440                 if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF, OB_FONT, OB_GPENCIL)) {
441                         ID *obdata = ob->data;
442                         if (ID_REAL_USERS(obdata) > 1) {
443                                 BKE_reportf(reports, RPT_ERROR,
444                                             "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
445                                             ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
446                                 changed = false;
447                         }
448
449                         if (ID_IS_LINKED(obdata)) {
450                                 BKE_reportf(reports, RPT_ERROR,
451                                             "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
452                                             ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
453                                 changed = false;
454                         }
455                 }
456
457                 if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
458                         ID *obdata = ob->data;
459                         Curve *cu;
460
461                         cu = ob->data;
462
463                         if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
464                                 BKE_reportf(reports, RPT_ERROR,
465                                             "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
466                                             ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
467                                 changed = false;
468                         }
469                         if (cu->key) {
470                                 BKE_reportf(reports, RPT_ERROR,
471                                             "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
472                                             ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
473                                 changed = false;
474                         }
475                 }
476
477                 if (ob->type == OB_FONT) {
478                         if (apply_rot || apply_loc) {
479                                 BKE_reportf(reports, RPT_ERROR,
480                                             "Font's can only have scale applied: \"%s\"",
481                                             ob->id.name + 2);
482                                 changed = false;
483                         }
484                 }
485
486                 if (ob->type == OB_GPENCIL) {
487                         bGPdata *gpd = ob->data;
488                         if (gpd) {
489                                 if (gpd->layers.first) {
490                                         /* Unsupported configuration */
491                                         bool has_unparented_layers = false;
492
493                                         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
494                                                 /* Parented layers aren't supported as we can't easily re-evaluate
495                                                  * the scene to sample parent movement */
496                                                 if (gpl->parent == NULL) {
497                                                         has_unparented_layers = true;
498                                                         break;
499                                                 }
500                                         }
501
502                                         if (has_unparented_layers == false) {
503                                                 BKE_reportf(reports, RPT_ERROR,
504                                                             "Can't apply to a GP datablock where all layers are parented: Object \"%s\", %s \"%s\", aborting",
505                                                             ob->id.name + 2, BKE_idcode_to_name(ID_GD), gpd->id.name + 2);
506                                                 changed = false;
507                                         }
508                                 }
509                                 else {
510                                         /* No layers/data */
511                                         BKE_reportf(reports, RPT_ERROR,
512                                                     "Can't apply to GP datablock with no layers: Object \"%s\", %s \"%s\", aborting",
513                                                     ob->id.name + 2, BKE_idcode_to_name(ID_GD), gpd->id.name + 2);
514                                 }
515                         }
516                 }
517
518                 if (ob->type == OB_LAMP) {
519                         Lamp *la = ob->data;
520                         if (la->type == LA_AREA) {
521                                 if (apply_rot || apply_loc) {
522                                         BKE_reportf(reports, RPT_ERROR,
523                                                     "Area Lights can only have scale applied: \"%s\"",
524                                                     ob->id.name + 2);
525                                         changed = false;
526                                 }
527                         }
528                 }
529         }
530         CTX_DATA_END;
531
532         if (!changed)
533                 return OPERATOR_CANCELLED;
534
535         changed = false;
536
537         /* now execute */
538         CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
539         {
540
541                 /* calculate rotation/scale matrix */
542                 if (apply_scale && apply_rot)
543                         BKE_object_to_mat3(ob, rsmat);
544                 else if (apply_scale)
545                         BKE_object_scale_to_mat3(ob, rsmat);
546                 else if (apply_rot) {
547                         float tmat[3][3], timat[3][3];
548
549                         /* simple rotation matrix */
550                         BKE_object_rot_to_mat3(ob, rsmat, true);
551
552                         /* correct for scale, note mul_m3_m3m3 has swapped args! */
553                         BKE_object_scale_to_mat3(ob, tmat);
554                         invert_m3_m3(timat, tmat);
555                         mul_m3_m3m3(rsmat, timat, rsmat);
556                         mul_m3_m3m3(rsmat, rsmat, tmat);
557                 }
558                 else
559                         unit_m3(rsmat);
560
561                 copy_m4_m3(mat, rsmat);
562
563                 /* calculate translation */
564                 if (apply_loc) {
565                         copy_v3_v3(mat[3], ob->loc);
566
567                         if (!(apply_scale && apply_rot)) {
568                                 float tmat[3][3];
569                                 /* correct for scale and rotation that is still applied */
570                                 BKE_object_to_mat3(ob, obmat);
571                                 invert_m3_m3(iobmat, obmat);
572                                 mul_m3_m3m3(tmat, rsmat, iobmat);
573                                 mul_m3_v3(tmat, mat[3]);
574                         }
575                 }
576
577                 /* apply to object data */
578                 if (ob->type == OB_MESH) {
579                         Mesh *me = ob->data;
580
581                         if (apply_scale)
582                                 multiresModifier_scale_disp(depsgraph, scene, ob);
583
584                         /* adjust data */
585                         BKE_mesh_transform(me, mat, true);
586
587                         /* update normals */
588                         BKE_mesh_calc_normals(me);
589                 }
590                 else if (ob->type == OB_ARMATURE) {
591                         ED_armature_transform_apply(bmain, ob, mat, do_props);
592                 }
593                 else if (ob->type == OB_LATTICE) {
594                         Lattice *lt = ob->data;
595
596                         BKE_lattice_transform(lt, mat, true);
597                 }
598                 else if (ob->type == OB_MBALL) {
599                         MetaBall *mb = ob->data;
600                         BKE_mball_transform(mb, mat, do_props);
601                 }
602                 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
603                         Curve *cu = ob->data;
604                         scale = mat3_to_scale(rsmat);
605                         BKE_curve_transform_ex(cu, mat, true, do_props, scale);
606                 }
607                 else if (ob->type == OB_FONT) {
608                         Curve *cu = ob->data;
609                         int i;
610
611                         scale = mat3_to_scale(rsmat);
612
613                         for (i = 0; i < cu->totbox; i++) {
614                                 TextBox *tb = &cu->tb[i];
615                                 tb->x *= scale;
616                                 tb->y *= scale;
617                                 tb->w *= scale;
618                                 tb->h *= scale;
619                         }
620
621                         if (do_props) {
622                                 cu->fsize *= scale;
623                         }
624                 }
625                 else if (ob->type == OB_GPENCIL) {
626                         bGPdata *gpd = ob->data;
627                         BKE_gpencil_transform(gpd, mat);
628                 }
629                 else if (ob->type == OB_CAMERA) {
630                         MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
631
632                         /* applying scale on camera actually scales clip's reconstruction.
633                          * of there's clip assigned to camera nothing to do actually.
634                          */
635                         if (!clip)
636                                 continue;
637
638                         if (apply_scale)
639                                 BKE_tracking_reconstruction_scale(&clip->tracking, ob->size);
640                 }
641                 else if (ob->type == OB_EMPTY) {
642                         /* It's possible for empties too, even though they don't
643                          * really have obdata, since we can simply apply the maximum
644                          * scaling to the empty's drawsize.
645                          *
646                          * Core Assumptions:
647                          * 1) Most scaled empties have uniform scaling
648                          *    (i.e. for visibility reasons), AND/OR
649                          * 2) Preserving non-uniform scaling is not that important,
650                          *    and is something that many users would be willing to
651                          *    sacrifice for having an easy way to do this.
652                          */
653
654                         if ((apply_loc == false) &&
655                             (apply_rot == false) &&
656                             (apply_scale == true))
657                         {
658                                 float max_scale = max_fff(fabsf(ob->size[0]), fabsf(ob->size[1]), fabsf(ob->size[2]));
659                                 ob->empty_drawsize *= max_scale;
660                         }
661                 }
662                 else if (ob->type == OB_LAMP) {
663                         Lamp *la = ob->data;
664                         if (la->type != LA_AREA) {
665                                 continue;
666                         }
667
668                         bool keeps_aspect_ratio = compare_ff_relative(rsmat[0][0], rsmat[1][1], FLT_EPSILON, 64);
669                         if ((la->area_shape == LA_AREA_SQUARE) && !keeps_aspect_ratio) {
670                                 la->area_shape = LA_AREA_RECT;
671                                 la->area_sizey = la->area_size;
672                         }
673                         else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) {
674                                 la->area_shape = LA_AREA_ELLIPSE;
675                                 la->area_sizey = la->area_size;
676                         }
677
678                         la->area_size *= rsmat[0][0];
679                         la->area_sizey *= rsmat[1][1];
680                         la->area_sizez *= rsmat[2][2];
681                 }
682                 else {
683                         continue;
684                 }
685
686                 if (apply_loc)
687                         zero_v3(ob->loc);
688                 if (apply_scale)
689                         ob->size[0] = ob->size[1] = ob->size[2] = 1.0f;
690                 if (apply_rot) {
691                         zero_v3(ob->rot);
692                         unit_qt(ob->quat);
693                         unit_axis_angle(ob->rotAxis, &ob->rotAngle);
694                 }
695
696                 BKE_object_where_is_calc(depsgraph, scene, ob);
697                 if (ob->type == OB_ARMATURE) {
698                         BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
699                 }
700
701                 ignore_parent_tx(C, bmain, scene, ob);
702
703                 DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
704
705                 changed = true;
706         }
707         CTX_DATA_END;
708
709         if (!changed) {
710                 BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
711                 return OPERATOR_CANCELLED;
712         }
713
714         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
715         return OPERATOR_FINISHED;
716 }
717
718 static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
719 {
720         Scene *scene = CTX_data_scene(C);
721         Depsgraph *depsgraph = CTX_data_depsgraph(C);
722         bool changed = false;
723
724         CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
725         {
726                 BKE_object_where_is_calc(depsgraph, scene, ob);
727                 BKE_object_apply_mat4(ob, ob->obmat, true, true);
728                 BKE_object_where_is_calc(depsgraph, scene, ob);
729
730                 /* update for any children that may get moved */
731                 DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
732
733                 changed = true;
734         }
735         CTX_DATA_END;
736
737         if (!changed)
738                 return OPERATOR_CANCELLED;
739
740         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
741         return OPERATOR_FINISHED;
742 }
743
744 void OBJECT_OT_visual_transform_apply(wmOperatorType *ot)
745 {
746         /* identifiers */
747         ot->name = "Apply Visual Transform";
748         ot->description = "Apply the object's visual transformation to its data";
749         ot->idname = "OBJECT_OT_visual_transform_apply";
750
751         /* api callbacks */
752         ot->exec = visual_transform_apply_exec;
753         ot->poll = ED_operator_scene_editable;
754
755         /* flags */
756         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
757 }
758
759 static int object_transform_apply_exec(bContext *C, wmOperator *op)
760 {
761         const bool loc = RNA_boolean_get(op->ptr, "location");
762         const bool rot = RNA_boolean_get(op->ptr, "rotation");
763         const bool sca = RNA_boolean_get(op->ptr, "scale");
764         const bool do_props = RNA_boolean_get(op->ptr, "properties");
765
766         if (loc || rot || sca) {
767                 return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
768         }
769         else {
770                 /* allow for redo */
771                 return OPERATOR_FINISHED;
772         }
773 }
774
775 void OBJECT_OT_transform_apply(wmOperatorType *ot)
776 {
777         /* identifiers */
778         ot->name = "Apply Object Transform";
779         ot->description = "Apply the object's transformation to its data";
780         ot->idname = "OBJECT_OT_transform_apply";
781
782         /* api callbacks */
783         ot->exec = object_transform_apply_exec;
784         ot->poll = ED_operator_objectmode;
785
786         /* flags */
787         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
788
789         RNA_def_boolean(ot->srna, "location", true, "Location", "");
790         RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "");
791         RNA_def_boolean(ot->srna, "scale", true, "Scale", "");
792         RNA_def_boolean(ot->srna, "properties", true, "Apply Properties",
793                         "Modify properties such as curve vertex radius, font size and bone envelope");
794 }
795
796 /********************* Set Object Center ************************/
797
798 enum {
799         GEOMETRY_TO_ORIGIN = 0,
800         ORIGIN_TO_GEOMETRY,
801         ORIGIN_TO_CURSOR,
802         ORIGIN_TO_CENTER_OF_MASS_SURFACE,
803         ORIGIN_TO_CENTER_OF_MASS_VOLUME,
804 };
805
806 static int object_origin_set_exec(bContext *C, wmOperator *op)
807 {
808         Main *bmain = CTX_data_main(C);
809         Scene *scene = CTX_data_scene(C);
810         Object *obact = CTX_data_active_object(C);
811         Object *obedit = CTX_data_edit_object(C);
812         Depsgraph *depsgraph = CTX_data_depsgraph(C);
813         Object *tob;
814         float cent[3], cent_neg[3], centn[3];
815         const float *cursor = scene->cursor.location;
816         int centermode = RNA_enum_get(op->ptr, "type");
817
818         ListBase ctx_data_list;
819         CollectionPointerLink *ctx_ob;
820         CollectionPointerLink *ctx_ob_act = NULL;
821
822         /* keep track of what is changed */
823         int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0;
824
825         if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
826                 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
827                 return OPERATOR_CANCELLED;
828         }
829
830         int around;
831         {
832                 PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
833                 if (RNA_property_is_set(op->ptr, prop_center)) {
834                         around = RNA_property_enum_get(op->ptr, prop_center);
835                 }
836                 else {
837                         if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_BOUNDS) {
838                                 around = V3D_AROUND_CENTER_BOUNDS;
839                         }
840                         else {
841                                 around = V3D_AROUND_CENTER_MEDIAN;
842                         }
843                         RNA_property_enum_set(op->ptr, prop_center, around);
844                 }
845         }
846
847         zero_v3(cent);
848
849         if (obedit) {
850                 if (obedit->type == OB_MESH) {
851                         Mesh *me = obedit->data;
852                         BMEditMesh *em = me->edit_btmesh;
853                         BMVert *eve;
854                         BMIter iter;
855
856                         if (centermode == ORIGIN_TO_CURSOR) {
857                                 copy_v3_v3(cent, cursor);
858                                 invert_m4_m4(obedit->imat, obedit->obmat);
859                                 mul_m4_v3(obedit->imat, cent);
860                         }
861                         else {
862                                 if (around == V3D_AROUND_CENTER_MEDIAN) {
863                                         if (em->bm->totvert) {
864                                                 const float total_div = 1.0f / (float)em->bm->totvert;
865                                                 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
866                                                         madd_v3_v3fl(cent, eve->co, total_div);
867                                                 }
868                                         }
869                                 }
870                                 else {
871                                         float min[3], max[3];
872                                         INIT_MINMAX(min, max);
873                                         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
874                                                 minmax_v3v3_v3(min, max, eve->co);
875                                         }
876                                         mid_v3_v3v3(cent, min, max);
877                                 }
878                         }
879
880                         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
881                                 sub_v3_v3(eve->co, cent);
882                         }
883
884                         EDBM_mesh_normals_update(em);
885                         tot_change++;
886                         DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
887                 }
888         }
889
890         CTX_data_selected_editable_objects(C, &ctx_data_list);
891
892         /* reset flags */
893         for (ctx_ob = ctx_data_list.first;
894              ctx_ob;
895              ctx_ob = ctx_ob->next)
896         {
897                 Object *ob = ctx_ob->ptr.data;
898                 ob->flag &= ~OB_DONE;
899
900                 /* move active first */
901                 if (ob == obact) {
902                         ctx_ob_act = ctx_ob;
903                 }
904         }
905
906         if (ctx_ob_act) {
907                 BLI_listbase_rotate_first(&ctx_data_list, (LinkData *)ctx_ob_act);
908         }
909
910         for (tob = bmain->object.first; tob; tob = tob->id.next) {
911                 if (tob->data)
912                         ((ID *)tob->data)->tag &= ~LIB_TAG_DOIT;
913                 if (tob->dup_group)
914                         ((ID *)tob->dup_group)->tag &= ~LIB_TAG_DOIT;
915         }
916
917         for (ctx_ob = ctx_data_list.first;
918              ctx_ob;
919              ctx_ob = ctx_ob->next)
920         {
921                 Object *ob = ctx_ob->ptr.data;
922
923                 if ((ob->flag & OB_DONE) == 0) {
924                         bool do_inverse_offset = false;
925                         ob->flag |= OB_DONE;
926
927                         if (centermode == ORIGIN_TO_CURSOR) {
928                                 copy_v3_v3(cent, cursor);
929                                 invert_m4_m4(ob->imat, ob->obmat);
930                                 mul_m4_v3(ob->imat, cent);
931                         }
932
933                         if (ob->data == NULL) {
934                                 /* special support for dupligroups */
935                                 if ((ob->transflag & OB_DUPLICOLLECTION) && ob->dup_group && (ob->dup_group->id.tag & LIB_TAG_DOIT) == 0) {
936                                         if (ID_IS_LINKED(ob->dup_group)) {
937                                                 tot_lib_error++;
938                                         }
939                                         else {
940                                                 if (centermode == ORIGIN_TO_CURSOR) {
941                                                         /* done */
942                                                 }
943                                                 else {
944                                                         float min[3], max[3];
945                                                         /* only bounds support */
946                                                         INIT_MINMAX(min, max);
947                                                         BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true);
948                                                         mid_v3_v3v3(cent, min, max);
949                                                         invert_m4_m4(ob->imat, ob->obmat);
950                                                         mul_m4_v3(ob->imat, cent);
951                                                 }
952
953                                                 add_v3_v3(ob->dup_group->dupli_ofs, cent);
954
955                                                 tot_change++;
956                                                 ob->dup_group->id.tag |= LIB_TAG_DOIT;
957                                                 do_inverse_offset = true;
958                                         }
959                                 }
960                         }
961                         else if (ID_IS_LINKED(ob->data)) {
962                                 tot_lib_error++;
963                         }
964
965                         if (obedit == NULL && ob->type == OB_MESH) {
966                                 Mesh *me = ob->data;
967
968                                 if (centermode == ORIGIN_TO_CURSOR) {
969                                         /* done */
970                                 }
971                                 else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
972                                         BKE_mesh_center_of_surface(me, cent);
973                                 }
974                                 else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) {
975                                         BKE_mesh_center_of_volume(me, cent);
976                                 }
977                                 else if (around == V3D_AROUND_CENTER_MEDIAN) {
978                                         BKE_mesh_center_median(me, cent);
979                                 }
980                                 else {
981                                         BKE_mesh_center_bounds(me, cent);
982                                 }
983
984                                 negate_v3_v3(cent_neg, cent);
985                                 BKE_mesh_translate(me, cent_neg, 1);
986
987                                 tot_change++;
988                                 me->id.tag |= LIB_TAG_DOIT;
989                                 do_inverse_offset = true;
990                         }
991                         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
992                                 Curve *cu = ob->data;
993
994                                 if      (centermode == ORIGIN_TO_CURSOR)     { /* done */ }
995                                 else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_curve_center_median(cu, cent); }
996                                 else                                         { BKE_curve_center_bounds(cu, cent); }
997
998                                 /* don't allow Z change if curve is 2D */
999                                 if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
1000                                         cent[2] = 0.0;
1001
1002                                 negate_v3_v3(cent_neg, cent);
1003                                 BKE_curve_translate(cu, cent_neg, 1);
1004
1005                                 tot_change++;
1006                                 cu->id.tag |= LIB_TAG_DOIT;
1007                                 do_inverse_offset = true;
1008
1009                                 if (obedit) {
1010                                         if (centermode == GEOMETRY_TO_ORIGIN) {
1011                                                 DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
1012                                         }
1013                                         break;
1014                                 }
1015                         }
1016                         else if (ob->type == OB_FONT) {
1017                                 /* get from bb */
1018
1019                                 Curve *cu = ob->data;
1020
1021                                 if (ob->bb == NULL && (centermode != ORIGIN_TO_CURSOR)) {
1022                                         /* do nothing*/
1023                                 }
1024                                 else {
1025                                         if (centermode == ORIGIN_TO_CURSOR) {
1026                                                 /* done */
1027                                         }
1028                                         else {
1029                                                 /* extra 0.5 is the height o above line */
1030                                                 cent[0] = 0.5f * (ob->bb->vec[4][0] + ob->bb->vec[0][0]);
1031                                                 cent[1] = 0.5f * (ob->bb->vec[0][1] + ob->bb->vec[2][1]);
1032                                         }
1033
1034                                         cent[2] = 0.0f;
1035
1036                                         cu->xof = cu->xof - cent[0];
1037                                         cu->yof = cu->yof - cent[1];
1038
1039                                         tot_change++;
1040                                         cu->id.tag |= LIB_TAG_DOIT;
1041                                         do_inverse_offset = true;
1042                                 }
1043                         }
1044                         else if (ob->type == OB_ARMATURE) {
1045                                 bArmature *arm = ob->data;
1046
1047                                 if (ID_REAL_USERS(arm) > 1) {
1048 #if 0
1049                                         BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature");
1050                                         return;
1051 #endif
1052                                         tot_multiuser_arm_error++;
1053                                 }
1054                                 else {
1055                                         /* Function to recenter armatures in editarmature.c
1056                                          * Bone + object locations are handled there.
1057                                          */
1058                                         ED_armature_origin_set(bmain, ob, cursor, centermode, around);
1059
1060                                         tot_change++;
1061                                         arm->id.tag |= LIB_TAG_DOIT;
1062                                         /* do_inverse_offset = true; */ /* docenter_armature() handles this */
1063
1064                                         BKE_object_where_is_calc(depsgraph, scene, ob);
1065                                         BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
1066
1067                                         ignore_parent_tx(C, bmain, scene, ob);
1068
1069                                         if (obedit)
1070                                                 break;
1071                                 }
1072                         }
1073                         else if (ob->type == OB_MBALL) {
1074                                 MetaBall *mb = ob->data;
1075
1076                                 if      (centermode == ORIGIN_TO_CURSOR)     { /* done */ }
1077                                 else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_mball_center_median(mb, cent); }
1078                                 else                                         { BKE_mball_center_bounds(mb, cent); }
1079
1080                                 negate_v3_v3(cent_neg, cent);
1081                                 BKE_mball_translate(mb, cent_neg);
1082
1083                                 tot_change++;
1084                                 mb->id.tag |= LIB_TAG_DOIT;
1085                                 do_inverse_offset = true;
1086
1087                                 if (obedit) {
1088                                         if (centermode == GEOMETRY_TO_ORIGIN) {
1089                                                 DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
1090                                         }
1091                                         break;
1092                                 }
1093                         }
1094                         else if (ob->type == OB_LATTICE) {
1095                                 Lattice *lt = ob->data;
1096
1097                                 if      (centermode == ORIGIN_TO_CURSOR)     { /* done */ }
1098                                 else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_lattice_center_median(lt, cent); }
1099                                 else                                         { BKE_lattice_center_bounds(lt, cent); }
1100
1101                                 negate_v3_v3(cent_neg, cent);
1102                                 BKE_lattice_translate(lt, cent_neg, 1);
1103
1104                                 tot_change++;
1105                                 lt->id.tag |= LIB_TAG_DOIT;
1106                                 do_inverse_offset = true;
1107                         }
1108                         else if (ob->type == OB_GPENCIL) {
1109                                 bGPdata *gpd = ob->data;
1110                                 float gpcenter[3];
1111                                 if (gpd) {
1112                                         if (centermode == ORIGIN_TO_GEOMETRY) {
1113                                                 zero_v3(gpcenter);
1114                                                 BKE_gpencil_centroid_3d(gpd, gpcenter);
1115                                                 add_v3_v3(gpcenter, ob->obmat[3]);
1116                                         }
1117                                         if (centermode == ORIGIN_TO_CURSOR) {
1118                                                 copy_v3_v3(gpcenter, cursor);
1119                                         }
1120                                         if ((centermode == ORIGIN_TO_GEOMETRY) || (centermode == ORIGIN_TO_CURSOR)) {
1121                                                 bGPDspoint *pt;
1122                                                 float imat[3][3], bmat[3][3];
1123                                                 float offset_global[3];
1124                                                 float offset_local[3];
1125                                                 int i;
1126
1127                                                 sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
1128                                                 copy_m3_m4(bmat, obact->obmat);
1129                                                 invert_m3_m3(imat, bmat);
1130                                                 mul_m3_v3(imat, offset_global);
1131                                                 mul_v3_m3v3(offset_local, imat, offset_global);
1132
1133                                                 float diff_mat[4][4];
1134                                                 float inverse_diff_mat[4][4];
1135
1136                                                 /* recalculate all strokes
1137                                                  * (all layers are considered without evaluating lock attributes) */
1138                                                 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1139                                                         /* calculate difference matrix */
1140                                                         ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
1141                                                         /* undo matrix */
1142                                                         invert_m4_m4(inverse_diff_mat, diff_mat);
1143                                                         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1144                                                                 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1145                                                                         /* skip strokes that are invalid for current view */
1146                                                                         if (ED_gpencil_stroke_can_use(C, gps) == false)
1147                                                                                 continue;
1148
1149                                                                         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1150                                                                                 float mpt[3];
1151                                                                                 mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
1152                                                                                 sub_v3_v3(mpt, offset_local);
1153                                                                                 mul_v3_m4v3(&pt->x, diff_mat, mpt);
1154                                                                         }
1155                                                                 }
1156                                                         }
1157                                                 }
1158                                                 DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1159
1160                                                 tot_change++;
1161                                                 if (centermode == ORIGIN_TO_GEOMETRY) {
1162                                                         copy_v3_v3(ob->loc, gpcenter);
1163                                                 }
1164                                                 ob->id.tag |= LIB_TAG_DOIT;
1165                                                 do_inverse_offset = true;
1166                                         }
1167                                         else {
1168                                                 BKE_report(op->reports, RPT_WARNING, "Grease Pencil Object does not support this set origin option");
1169                                         }
1170                                 }
1171                         }
1172
1173                         /* offset other selected objects */
1174                         if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
1175                                 CollectionPointerLink *ctx_link_other;
1176                                 float obmat[4][4];
1177
1178                                 /* was the object data modified
1179                                  * note: the functions above must set 'cent' */
1180
1181                                 /* convert the offset to parent space */
1182                                 BKE_object_to_mat4(ob, obmat);
1183                                 mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
1184
1185                                 add_v3_v3(ob->loc, centn);
1186
1187                                 BKE_object_where_is_calc(depsgraph, scene, ob);
1188                                 if (ob->type == OB_ARMATURE) {
1189                                         BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
1190                                 }
1191
1192                                 ignore_parent_tx(C, bmain, scene, ob);
1193
1194                                 /* other users? */
1195                                 //CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
1196                                 //{
1197
1198                                 /* use existing context looper */
1199                                 for (ctx_link_other = ctx_data_list.first;
1200                                      ctx_link_other;
1201                                      ctx_link_other = ctx_link_other->next)
1202                                 {
1203                                         Object *ob_other = ctx_link_other->ptr.data;
1204
1205                                         if ((ob_other->flag & OB_DONE) == 0 &&
1206                                             ((ob->data && (ob->data == ob_other->data)) ||
1207                                              (ob->dup_group == ob_other->dup_group &&
1208                                               (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION)))
1209                                         {
1210                                                 ob_other->flag |= OB_DONE;
1211                                                 DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1212
1213                                                 mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
1214                                                 add_v3_v3(ob_other->loc, centn);
1215
1216                                                 BKE_object_where_is_calc(depsgraph, scene, ob_other);
1217                                                 if (ob_other->type == OB_ARMATURE) {
1218                                                         /* needed for bone parents */
1219                                                         BKE_pose_where_is(depsgraph, scene, ob_other);
1220                                                 }
1221                                                 ignore_parent_tx(C, bmain, scene, ob_other);
1222                                         }
1223                                 }
1224                                 //CTX_DATA_END;
1225                         }
1226                 }
1227         }
1228         BLI_freelistN(&ctx_data_list);
1229
1230         for (tob = bmain->object.first; tob; tob = tob->id.next) {
1231                 if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) {
1232                         BKE_object_batch_cache_dirty_tag(tob);
1233                         DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1234                 }
1235         }
1236
1237         if (tot_change) {
1238                 WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
1239         }
1240
1241         /* Warn if any errors occurred */
1242         if (tot_lib_error + tot_multiuser_arm_error) {
1243                 BKE_reportf(op->reports, RPT_WARNING, "%i object(s) not centered, %i changed:", tot_lib_error + tot_multiuser_arm_error, tot_change);
1244                 if (tot_lib_error)
1245                         BKE_reportf(op->reports, RPT_WARNING, "|%i linked library object(s)", tot_lib_error);
1246                 if (tot_multiuser_arm_error)
1247                         BKE_reportf(op->reports, RPT_WARNING, "|%i multiuser armature object(s)", tot_multiuser_arm_error);
1248         }
1249
1250         return OPERATOR_FINISHED;
1251 }
1252
1253 void OBJECT_OT_origin_set(wmOperatorType *ot)
1254 {
1255         static const EnumPropertyItem prop_set_center_types[] = {
1256                 {GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"},
1257                 {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry",
1258                  "Calculate the center of geometry based on the current pivot point (median, otherwise bounding-box)"},
1259                 {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor",
1260                  "Move object origin to position of the 3D cursor"},
1261                 /* Intentional naming mismatch since some scripts refer to this. */
1262                 {ORIGIN_TO_CENTER_OF_MASS_SURFACE, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass (Surface)",
1263                  "Calculate the center of mass from the surface area"},
1264                 {ORIGIN_TO_CENTER_OF_MASS_VOLUME, "ORIGIN_CENTER_OF_VOLUME", 0, "Origin to Center of Mass (Volume)",
1265                  "Calculate the center of mass from the volume (must be manifold geometry with consistent normals)"},
1266                 {0, NULL, 0, NULL, NULL}
1267         };
1268
1269         static const EnumPropertyItem prop_set_bounds_types[] = {
1270                 {V3D_AROUND_CENTER_MEDIAN, "MEDIAN", 0, "Median Center", ""},
1271                 {V3D_AROUND_CENTER_BOUNDS, "BOUNDS", 0, "Bounds Center", ""},
1272                 {0, NULL, 0, NULL, NULL}
1273         };
1274
1275         /* identifiers */
1276         ot->name = "Set Origin";
1277         ot->description = "Set the object's origin, by either moving the data, or set to center of data, or use 3D cursor";
1278         ot->idname = "OBJECT_OT_origin_set";
1279
1280         /* api callbacks */
1281         ot->invoke = WM_menu_invoke;
1282         ot->exec = object_origin_set_exec;
1283
1284         ot->poll = ED_operator_scene_editable;
1285
1286         /* flags */
1287         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1288
1289         ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
1290         RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", "");
1291 }
1292
1293 /* -------------------------------------------------------------------- */
1294 /** \name Transform Axis Target
1295  *
1296  * Note this is an experemental operator to point lamps/cameras at objects.
1297  * We may re-work how this behaves based on user feedback.
1298  * - campbell.
1299  * \{ */
1300
1301 /* When using multiple objects, apply their relative rotational offset to the active object. */
1302 #define USE_RELATIVE_ROTATION
1303 /* Disable overlays, ignoring user setting (lamp wire gets in the way). */
1304 #define USE_RENDER_OVERRIDE
1305 /* Calculate a depth if the cursor isn't already over a depth (not essential but feels buggy without). */
1306 #define USE_FAKE_DEPTH_INIT
1307
1308 struct XFormAxisItem {
1309         Object *ob;
1310         float rot_mat[3][3];
1311         void *obtfm;
1312         float xform_dist;
1313
1314 #ifdef USE_RELATIVE_ROTATION
1315         /* use when translating multiple */
1316         float xform_rot_offset[3][3];
1317 #endif
1318 };
1319
1320 struct XFormAxisData {
1321         ViewContext vc;
1322         struct {
1323                 float depth;
1324                 float normal[3];
1325                 bool is_depth_valid;
1326                 bool is_normal_valid;
1327         } prev;
1328
1329         struct XFormAxisItem *object_data;
1330         uint object_data_len;
1331         bool is_translate;
1332
1333         int init_event;
1334 };
1335
1336 #ifdef USE_FAKE_DEPTH_INIT
1337 static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *xfd, const int mval[2])
1338 {
1339         struct XFormAxisItem *item = xfd->object_data;
1340         float view_co_a[3], view_co_b[3];
1341         const float mval_fl[2] = {UNPACK2(mval)};
1342         ED_view3d_win_to_ray(xfd->vc.ar, mval_fl, view_co_a, view_co_b);
1343         add_v3_v3(view_co_b, view_co_a);
1344         float center[3] = {0.0f};
1345         int   center_tot = 0;
1346         for (int i = 0; i < xfd->object_data_len; i++, item++) {
1347                 const Object *ob = item->ob;
1348                 const float *ob_co_a = ob->obmat[3];
1349                 float        ob_co_b[3];
1350                 add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]);
1351                 float view_isect[3], ob_isect[3];
1352                 if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) {
1353                         add_v3_v3(center, view_isect);
1354                         center_tot += 1;
1355                 }
1356         }
1357         if (center_tot) {
1358                 mul_v3_fl(center, 1.0f / center_tot);
1359                 float center_proj[3];
1360                 ED_view3d_project(xfd->vc.ar, center, center_proj);
1361                 xfd->prev.depth = center_proj[2];
1362                 xfd->prev.is_depth_valid = true;
1363         }
1364 }
1365 #endif  /* USE_FAKE_DEPTH_INIT */
1366
1367 static bool object_is_target_compat(const Object *ob)
1368 {
1369         if (ob->type == OB_LAMP) {
1370                 const Lamp *la = ob->data;
1371                 if (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)) {
1372                         return true;
1373                 }
1374         }
1375         /* We might want to enable this later, for now just lamps */
1376 #if 0
1377         else if (ob->type == OB_CAMERA) {
1378                 return true;
1379         }
1380 #endif
1381         return false;
1382 }
1383
1384 static void object_transform_axis_target_free_data(wmOperator *op)
1385 {
1386         struct XFormAxisData *xfd = op->customdata;
1387         struct XFormAxisItem *item = xfd->object_data;
1388
1389 #ifdef USE_RENDER_OVERRIDE
1390         if (xfd->vc.rv3d->depths) {
1391                 xfd->vc.rv3d->depths->damaged = true;
1392         }
1393 #endif
1394
1395         for (int i = 0; i < xfd->object_data_len; i++, item++) {
1396                 MEM_freeN(item->obtfm);
1397         }
1398         MEM_freeN(xfd->object_data);
1399         MEM_freeN(xfd);
1400         op->customdata = NULL;
1401 }
1402
1403 /* We may want to expose as alternative to: BKE_object_apply_rotation */
1404 static void object_apply_rotation(Object *ob, const float rmat[3][3])
1405 {
1406         float size[3];
1407         float loc[3];
1408         float rmat4[4][4];
1409         copy_m4_m3(rmat4, rmat);
1410
1411         copy_v3_v3(size, ob->size);
1412         copy_v3_v3(loc, ob->loc);
1413         BKE_object_apply_mat4(ob, rmat4, true, true);
1414         copy_v3_v3(ob->size, size);
1415         copy_v3_v3(ob->loc, loc);
1416 }
1417 /* We may want to extract this to: BKE_object_apply_location */
1418 static void object_apply_location(Object *ob, const float loc[3])
1419 {
1420         /* quick but weak */
1421         Object ob_prev = *ob;
1422         float mat[4][4];
1423         copy_m4_m4(mat, ob->obmat);
1424         copy_v3_v3(mat[3], loc);
1425         BKE_object_apply_mat4(ob, mat, true, true);
1426         copy_v3_v3(mat[3], ob->loc);
1427         *ob = ob_prev;
1428         copy_v3_v3(ob->loc, mat[3]);
1429 }
1430
1431 static void object_orient_to_location(
1432         Object *ob, float rot_orig[3][3], const float axis[3], const float location[3])
1433 {
1434         float delta[3];
1435         sub_v3_v3v3(delta, ob->obmat[3], location);
1436         if (normalize_v3(delta) != 0.0f) {
1437                 if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
1438                         float delta_rot[3][3];
1439                         float final_rot[3][3];
1440                         rotation_between_vecs_to_mat3(delta_rot, axis, delta);
1441
1442                         mul_m3_m3m3(final_rot, delta_rot, rot_orig);
1443
1444                         object_apply_rotation(ob, final_rot);
1445
1446                         DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
1447                 }
1448         }
1449 }
1450
1451 static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
1452 {
1453         struct XFormAxisData *xfd = op->customdata;
1454         struct XFormAxisItem *item = xfd->object_data;
1455         for (int i = 0; i < xfd->object_data_len; i++, item++) {
1456                 BKE_object_tfm_restore(item->ob, item->obtfm);
1457                 DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM);
1458                 WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
1459         }
1460
1461         object_transform_axis_target_free_data(op);
1462 }
1463
1464 static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1465 {
1466         ViewContext vc;
1467         ED_view3d_viewcontext_init(C, &vc);
1468
1469         if (vc.obact == NULL || !object_is_target_compat(vc.obact)) {
1470                 /* Falls back to texture space transform. */
1471                 return OPERATOR_PASS_THROUGH;
1472         }
1473
1474
1475 #ifdef USE_RENDER_OVERRIDE
1476         int flag2_prev = vc.v3d->flag2;
1477         vc.v3d->flag2 |= V3D_RENDER_OVERRIDE;
1478 #endif
1479
1480         ED_view3d_autodist_init(vc.depsgraph, vc.ar, vc.v3d, 0);
1481
1482         if (vc.rv3d->depths != NULL) {
1483                 vc.rv3d->depths->damaged = true;
1484         }
1485         ED_view3d_depth_update(vc.ar);
1486
1487 #ifdef USE_RENDER_OVERRIDE
1488         vc.v3d->flag2 = flag2_prev;
1489 #endif
1490
1491         if (vc.rv3d->depths == NULL) {
1492                 BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
1493                 return OPERATOR_CANCELLED;
1494         }
1495
1496         ED_region_tag_redraw(vc.ar);
1497
1498         struct XFormAxisData *xfd;
1499         xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__);
1500
1501         /* Don't change this at runtime. */
1502         xfd->vc = vc;
1503         xfd->vc.mval[0] = event->mval[0];
1504         xfd->vc.mval[1] = event->mval[1];
1505
1506         xfd->prev.depth = 1.0f;
1507         xfd->prev.is_depth_valid = false;
1508         xfd->prev.is_normal_valid = false;
1509         xfd->is_translate = false;
1510
1511         xfd->init_event = WM_userdef_event_type_from_keymap_type(event->type);
1512
1513         {
1514                 struct XFormAxisItem *object_data = NULL;
1515                 BLI_array_declare(object_data);
1516
1517                 struct XFormAxisItem *item = BLI_array_append_ret(object_data);
1518                 item->ob = xfd->vc.obact;
1519
1520                 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
1521                 {
1522                         if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) {
1523                                 item = BLI_array_append_ret(object_data);
1524                                 item->ob = ob;
1525                         }
1526                 }
1527                 CTX_DATA_END;
1528
1529                 xfd->object_data = object_data;
1530                 xfd->object_data_len = BLI_array_len(object_data);
1531
1532                 if (xfd->object_data_len != BLI_array_len(object_data)) {
1533                         xfd->object_data = MEM_reallocN(xfd->object_data, xfd->object_data_len * sizeof(*xfd->object_data));
1534                 }
1535         }
1536
1537         {
1538                 struct XFormAxisItem *item = xfd->object_data;
1539                 for (int i = 0; i < xfd->object_data_len; i++, item++) {
1540                         item->obtfm = BKE_object_tfm_backup(item->ob);
1541                         BKE_object_rot_to_mat3(item->ob, item->rot_mat, true);
1542                 }
1543         }
1544
1545         WM_event_add_modal_handler(C, op);
1546
1547         return OPERATOR_RUNNING_MODAL;
1548 }
1549
1550 static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const wmEvent *event)
1551 {
1552         struct XFormAxisData *xfd = op->customdata;
1553         ARegion *ar = xfd->vc.ar;
1554
1555         view3d_operator_needs_opengl(C);
1556
1557         const bool is_translate = (event->ctrl != 0);
1558         const bool is_translate_init = is_translate && (xfd->is_translate != is_translate);
1559
1560         if (event->type == MOUSEMOVE || is_translate_init) {
1561                 const ViewDepths *depths = xfd->vc.rv3d->depths;
1562                 if (depths &&
1563                     ((unsigned int)event->mval[0] < depths->w) &&
1564                     ((unsigned int)event->mval[1] < depths->h))
1565                 {
1566                         double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
1567                         float location_world[3];
1568                         if (depth == 1.0f) {
1569                                 if (xfd->prev.is_depth_valid) {
1570                                         depth = (double)xfd->prev.depth;
1571                                 }
1572                         }
1573
1574 #ifdef USE_FAKE_DEPTH_INIT
1575                         /* First time only. */
1576                         if (depth == 1.0f) {
1577                                 if (xfd->prev.is_depth_valid == false) {
1578                                         object_transform_axis_target_calc_depth_init(xfd, event->mval);
1579                                         if (xfd->prev.is_depth_valid) {
1580                                                 depth = (double)xfd->prev.depth;
1581                                         }
1582                                 }
1583                         }
1584 #endif
1585
1586                         if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
1587                                 xfd->prev.depth = depth;
1588                                 xfd->prev.is_depth_valid = true;
1589                                 if (ED_view3d_depth_unproject(ar, event->mval, depth, location_world)) {
1590                                         if (is_translate) {
1591
1592                                                 float normal[3];
1593                                                 bool normal_found = false;
1594                                                 if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) {
1595                                                         normal_found = true;
1596
1597                                                         /* cheap attempt to smooth normals out a bit! */
1598                                                         const uint ofs = 2;
1599                                                         for (uint x = -ofs; x <= ofs; x += ofs / 2) {
1600                                                                 for (uint y = -ofs; y <= ofs; y += ofs / 2) {
1601                                                                         if (x != 0 && y != 0) {
1602                                                                                 int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
1603                                                                                 float n[3];
1604                                                                                 if (ED_view3d_depth_read_cached_normal(
1605                                                                                         &xfd->vc, mval_ofs, n))
1606                                                                                 {
1607                                                                                         add_v3_v3(normal, n);
1608                                                                                 }
1609                                                                         }
1610                                                                 }
1611                                                         }
1612                                                         normalize_v3(normal);
1613                                                 }
1614                                                 else if (xfd->prev.is_normal_valid) {
1615                                                         copy_v3_v3(normal, xfd->prev.normal);
1616                                                         normal_found = true;
1617                                                 }
1618
1619                                                 if (normal_found) {
1620 #ifdef USE_RELATIVE_ROTATION
1621                                                         if (is_translate_init && xfd->object_data_len > 1) {
1622                                                                 float xform_rot_offset_inv_first[3][3];
1623                                                                 struct XFormAxisItem *item = xfd->object_data;
1624                                                                 for (int i = 0; i < xfd->object_data_len; i++, item++) {
1625                                                                         copy_m3_m4(item->xform_rot_offset, item->ob->obmat);
1626                                                                         normalize_m3(item->xform_rot_offset);
1627
1628                                                                         if (i == 0) {
1629                                                                                 invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset);
1630                                                                         }
1631                                                                         else {
1632                                                                                 mul_m3_m3m3(item->xform_rot_offset,
1633                                                                                             item->xform_rot_offset,
1634                                                                                             xform_rot_offset_inv_first);
1635                                                                         }
1636                                                                 }
1637                                                         }
1638
1639 #endif
1640
1641                                                         struct XFormAxisItem *item = xfd->object_data;
1642                                                         for (int i = 0; i < xfd->object_data_len; i++, item++) {
1643                                                                 if (is_translate_init) {
1644                                                                         float ob_axis[3];
1645                                                                         item->xform_dist = len_v3v3(item->ob->obmat[3], location_world);
1646                                                                         normalize_v3_v3(ob_axis, item->ob->obmat[2]);
1647                                                                         /* Scale to avoid adding distance when moving between surfaces. */
1648                                                                         float scale = fabsf(dot_v3v3(ob_axis, normal));
1649                                                                         item->xform_dist *= scale;
1650                                                                 }
1651
1652                                                                 float target_normal[3];
1653                                                                 copy_v3_v3(target_normal, normal);
1654
1655 #ifdef USE_RELATIVE_ROTATION
1656                                                                 if (i != 0) {
1657                                                                         mul_m3_v3(item->xform_rot_offset, target_normal);
1658                                                                 }
1659 #endif
1660                                                                 {
1661                                                                         float loc[3];
1662
1663                                                                         copy_v3_v3(loc, location_world);
1664                                                                         madd_v3_v3fl(loc, target_normal, item->xform_dist);
1665                                                                         object_apply_location(item->ob, loc);
1666                                                                         /* so orient behaves as expected */
1667                                                                         copy_v3_v3(item->ob->obmat[3], loc);
1668                                                                 }
1669
1670                                                                 object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
1671                                                                 WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
1672                                                         }
1673                                                         copy_v3_v3(xfd->prev.normal, normal);
1674                                                         xfd->prev.is_normal_valid = true;
1675                                                 }
1676                                         }
1677                                         else {
1678                                                 struct XFormAxisItem *item = xfd->object_data;
1679                                                 for (int i = 0; i < xfd->object_data_len; i++, item++) {
1680                                                         object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
1681                                                         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
1682                                                 }
1683                                                 xfd->prev.is_normal_valid = false;
1684                                         }
1685                                 }
1686                         }
1687                 }
1688                 xfd->is_translate = is_translate;
1689
1690                 ED_region_tag_redraw(xfd->vc.ar);
1691         }
1692
1693         bool is_finished = false;
1694
1695         if (ISMOUSE(xfd->init_event)) {
1696                 if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) {
1697                         is_finished = true;
1698                 }
1699         }
1700         else {
1701                 if (ELEM(event->type, LEFTMOUSE, RETKEY, PADENTER)) {
1702                         is_finished = true;
1703                 }
1704         }
1705
1706         if (is_finished) {
1707                 object_transform_axis_target_free_data(op);
1708                 return OPERATOR_FINISHED;
1709         }
1710         else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
1711                 object_transform_axis_target_cancel(C, op);
1712                 return OPERATOR_CANCELLED;
1713         }
1714
1715
1716         return OPERATOR_RUNNING_MODAL;
1717 }
1718
1719 void OBJECT_OT_transform_axis_target(wmOperatorType *ot)
1720 {
1721         /* identifiers */
1722         ot->name = "Interactive Light Track to Cursor";
1723         ot->description = "Interactively point cameras and lights to a location (Ctrl translates)";
1724         ot->idname = "OBJECT_OT_transform_axis_target";
1725
1726         /* api callbacks */
1727         ot->invoke = object_transform_axis_target_invoke;
1728         ot->cancel = object_transform_axis_target_cancel;
1729         ot->modal = object_transform_axis_target_modal;
1730         ot->poll = ED_operator_region_view3d_active;
1731
1732         /* flags */
1733         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1734 }
1735
1736 #undef USE_RELATIVE_ROTATION
1737
1738 /** \} */