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