DRW: show image empty frame when the 'side' is hidden
[blender.git] / source / blender / blenkernel / intern / object.c
index 4e1ba0032284ed0a63265a3e4cac46df8e8487e4..1743060aa97f823a52786afef965466458ea0094 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/blenkernel/intern/object.c
- *  \ingroup bke
+/** \file
+ * \ingroup bke
  */
 
 
@@ -34,6 +26,8 @@
 #include <math.h>
 #include <stdio.h>
 
+#include "CLG_log.h"
+
 #include "MEM_guardedalloc.h"
 
 #include "DNA_anim_types.h"
@@ -44,7 +38,7 @@
 #include "DNA_gpencil_types.h"
 #include "DNA_gpencil_modifier_types.h"
 #include "DNA_key_types.h"
-#include "DNA_lamp_types.h"
+#include "DNA_light_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_material_types.h"
 #include "DNA_meta_types.h"
@@ -91,7 +85,7 @@
 #include "BKE_gpencil_modifier.h"
 #include "BKE_icons.h"
 #include "BKE_key.h"
-#include "BKE_lamp.h"
+#include "BKE_light.h"
 #include "BKE_layer.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h"
 #include "CCGSubSurf.h"
 #include "atomic_ops.h"
 
+static CLG_LogRef LOG = {"bke.object"};
+
 /* Vertex parent modifies original BMesh which is not safe for threading.
  * Ideally such a modification should be handled as a separate DAG update
  * callback for mesh datablock, but for until it is actually supported use
@@ -155,7 +151,7 @@ void BKE_object_workob_clear(Object *workob)
 {
        memset(workob, 0, sizeof(Object));
 
-       workob->size[0] = workob->size[1] = workob->size[2] = 1.0f;
+       workob->scale[0] = workob->scale[1] = workob->scale[2] = 1.0f;
        workob->dscale[0] = workob->dscale[1] = workob->dscale[2] = 1.0f;
        workob->rotmode = ROT_MODE_EUL;
 }
@@ -454,10 +450,7 @@ void BKE_object_free_derived_caches(Object *ob)
                }
        }
 
-       if (ob->bb) {
-               MEM_freeN(ob->bb);
-               ob->bb = NULL;
-       }
+       MEM_SAFE_FREE(ob->runtime.bb);
 
        object_update_from_subsurf_ccg(ob);
        BKE_object_free_derived_mesh_caches(ob);
@@ -470,7 +463,7 @@ void BKE_object_free_derived_caches(Object *ob)
                        ob->data = ob->runtime.mesh_orig;
                }
                /* Evaluated mesh points to edit mesh, but does not own it. */
-               mesh_eval->edit_btmesh = NULL;
+               mesh_eval->edit_mesh = NULL;
                BKE_mesh_free(mesh_eval);
                BKE_libblock_free_data(&mesh_eval->id, false);
                MEM_freeN(mesh_eval);
@@ -570,7 +563,7 @@ void BKE_object_free(Object *ob)
        MEM_SAFE_FREE(ob->mat);
        MEM_SAFE_FREE(ob->matbits);
        MEM_SAFE_FREE(ob->iuser);
-       MEM_SAFE_FREE(ob->bb);
+       MEM_SAFE_FREE(ob->runtime.bb);
 
        BLI_freelistN(&ob->defbase);
        BLI_freelistN(&ob->fmaps);
@@ -618,7 +611,7 @@ bool BKE_object_is_in_editmode(const Object *ob)
 
        switch (ob->type) {
                case OB_MESH:
-                       return ((Mesh *)ob->data)->edit_btmesh != NULL;
+                       return ((Mesh *)ob->data)->edit_mesh != NULL;
                case OB_ARMATURE:
                        return ((bArmature *)ob->data)->edbo != NULL;
                case OB_FONT:
@@ -647,7 +640,7 @@ bool BKE_object_data_is_in_editmode(const ID *id)
        BLI_assert(OB_DATA_SUPPORT_EDITMODE(type));
        switch (type) {
                case ID_ME:
-                       return ((const Mesh *)id)->edit_btmesh != NULL;
+                       return ((const Mesh *)id)->edit_mesh != NULL;
                case ID_CU:
                        return (
                                (((const Curve *)id)->editnurb != NULL) ||
@@ -670,7 +663,7 @@ bool BKE_object_is_in_wpaint_select_vert(const Object *ob)
        if (ob->type == OB_MESH) {
                Mesh *me = ob->data;
                return ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
-                       (me->edit_btmesh == NULL) &&
+                       (me->edit_mesh == NULL) &&
                        (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX));
        }
 
@@ -775,14 +768,14 @@ static const char *get_obdata_defname(int type)
                case OB_FONT: return DATA_("Text");
                case OB_MBALL: return DATA_("Mball");
                case OB_CAMERA: return DATA_("Camera");
-               case OB_LAMP: return DATA_("Light");
+               case OB_LAMP: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
                case OB_LATTICE: return DATA_("Lattice");
                case OB_ARMATURE: return DATA_("Armature");
                case OB_SPEAKER: return DATA_("Speaker");
                case OB_EMPTY: return DATA_("Empty");
                case OB_GPENCIL: return DATA_("GPencil");
                default:
-                       printf("get_obdata_defname: Internal error, bad type: %d\n", type);
+                       CLOG_ERROR(&LOG, "Internal error, bad type: %d", type);
                        return DATA_("Empty");
        }
 }
@@ -800,7 +793,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
                case OB_FONT:      return BKE_curve_add(bmain, name, OB_FONT);
                case OB_MBALL:     return BKE_mball_add(bmain, name);
                case OB_CAMERA:    return BKE_camera_add(bmain, name);
-               case OB_LAMP:      return BKE_lamp_add(bmain, name);
+               case OB_LAMP:      return BKE_light_add(bmain, name);
                case OB_LATTICE:   return BKE_lattice_add(bmain, name);
                case OB_ARMATURE:  return BKE_armature_add(bmain, name);
                case OB_SPEAKER:   return BKE_speaker_add(bmain, name);
@@ -808,7 +801,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
                case OB_GPENCIL:   return BKE_gpencil_data_addnew(bmain, name);
                case OB_EMPTY:     return NULL;
                default:
-                       printf("%s: Internal error, bad type: %d\n", __func__, type);
+                       CLOG_ERROR(&LOG, "Internal error, bad type: %d", type);
                        return NULL;
        }
 }
@@ -817,10 +810,9 @@ void BKE_object_init(Object *ob)
 {
        /* BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ob, id)); */  /* ob->type is already initialized... */
 
-       ob->col[0] = ob->col[1] = ob->col[2] = 1.0;
-       ob->col[3] = 1.0;
+       copy_v4_fl(ob->color, 1.0f);
 
-       ob->size[0] = ob->size[1] = ob->size[2] = 1.0;
+       ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0;
        ob->dscale[0] = ob->dscale[1] = ob->dscale[2] = 1.0;
 
        /* objects should default to having Euler XYZ rotations,
@@ -857,9 +849,7 @@ void BKE_object_init(Object *ob)
                ob->upflag = OB_POSZ;
        }
 
-       ob->dupon = 1; ob->dupoff = 0;
-       ob->dupsta = 1; ob->dupend = 100;
-       ob->dupfacesca = 1.0;
+       ob->instance_faces_scale = 1.0;
 
        ob->col_group = 0x01;
        ob->col_mask = 0xffff;
@@ -873,8 +863,6 @@ void BKE_object_init(Object *ob)
 
        /* Animation Visualization defaults */
        animviz_settings_init(&ob->avs);
-
-       ob->display.flag = OB_SHOW_SHADOW;
 }
 
 /* more general add: creates minimum required data, but without vertices etc. */
@@ -1314,12 +1302,12 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
        copy_v3_v3(ob_tar->rotAxis, ob_src->rotAxis);
        ob_tar->rotAngle = ob_src->rotAngle;
        ob_tar->rotmode = ob_src->rotmode;
-       copy_v3_v3(ob_tar->size, ob_src->size);
+       copy_v3_v3(ob_tar->scale, ob_src->scale);
 }
 
 /**
  * Only copy internal data of Object ID from source to already allocated/initialized destination.
- * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ * You probably never want to use that directly, use BKE_id_copy or BKE_id_copy_ex for typical needs.
  *
  * WARNING! This function will not handle ID user count!
  *
@@ -1332,7 +1320,7 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con
        ShaderFxData *fx;
 
        /* Do not copy runtime data. */
-       BKE_object_runtime_reset(ob_dst);
+       BKE_object_runtime_reset_on_copy(ob_dst, flag);
 
        /* We never handle usercount here for own data. */
        const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
@@ -1351,7 +1339,7 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con
 
        if (ob_src->iuser) ob_dst->iuser = MEM_dupallocN(ob_src->iuser);
 
-       if (ob_src->bb) ob_dst->bb = MEM_dupallocN(ob_src->bb);
+       if (ob_src->runtime.bb) ob_dst->runtime.bb = MEM_dupallocN(ob_src->runtime.bb);
 
        BLI_listbase_clear(&ob_dst->modifiers);
 
@@ -1431,7 +1419,7 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con
 Object *BKE_object_copy(Main *bmain, const Object *ob)
 {
        Object *ob_copy;
-       BKE_id_copy_ex(bmain, &ob->id, (ID **)&ob_copy, 0, false);
+       BKE_id_copy(bmain, &ob->id, (ID **)&ob_copy);
 
        /* We increase object user count when linking to Collections. */
        id_us_min(&ob_copy->id);
@@ -1439,6 +1427,240 @@ Object *BKE_object_copy(Main *bmain, const Object *ob)
        return ob_copy;
 }
 
+Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag)
+{
+       Material ***matarar;
+       ID *id;
+       int a, didit;
+       Object *obn = BKE_object_copy(bmain, ob);
+
+       /* 0 == full linked. */
+       if (dupflag == 0) {
+               return obn;
+       }
+
+#define ID_NEW_REMAP_US(a)     if (      (a)->id.newid) { (a) = (void *)(a)->id.newid;       (a)->id.us++; }
+#define ID_NEW_REMAP_US2(a)    if (((ID *)a)->newid)    { (a) = ((ID  *)a)->newid;     ((ID *)a)->us++;    }
+
+       /* duplicates using userflags */
+       if (dupflag & USER_DUP_ACT) {
+               BKE_animdata_copy_id_action(bmain, &obn->id, true);
+       }
+
+       if (dupflag & USER_DUP_MAT) {
+               for (a = 0; a < obn->totcol; a++) {
+                       id = (ID *)obn->mat[a];
+                       if (id) {
+                               ID_NEW_REMAP_US(obn->mat[a])
+                               else {
+                                       obn->mat[a] = ID_NEW_SET(obn->mat[a], BKE_material_copy(bmain, obn->mat[a]));
+                               }
+                               id_us_min(id);
+
+                               if (dupflag & USER_DUP_ACT) {
+                                       BKE_animdata_copy_id_action(bmain, &obn->mat[a]->id, true);
+                               }
+                       }
+               }
+       }
+       if (dupflag & USER_DUP_PSYS) {
+               ParticleSystem *psys;
+               for (psys = obn->particlesystem.first; psys; psys = psys->next) {
+                       id = (ID *) psys->part;
+                       if (id) {
+                               ID_NEW_REMAP_US(psys->part)
+                               else {
+                                       psys->part = ID_NEW_SET(psys->part, BKE_particlesettings_copy(bmain, psys->part));
+                               }
+
+                               if (dupflag & USER_DUP_ACT) {
+                                       BKE_animdata_copy_id_action(bmain, &psys->part->id, true);
+                               }
+
+                               id_us_min(id);
+                       }
+               }
+       }
+
+       id = obn->data;
+       didit = 0;
+
+       switch (obn->type) {
+               case OB_MESH:
+                       if (dupflag & USER_DUP_MESH) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_mesh_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_CURVE:
+                       if (dupflag & USER_DUP_CURVE) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_SURF:
+                       if (dupflag & USER_DUP_SURF) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_FONT:
+                       if (dupflag & USER_DUP_FONT) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_MBALL:
+                       if (dupflag & USER_DUP_MBALL) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_mball_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_LAMP:
+                       if (dupflag & USER_DUP_LAMP) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_light_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_ARMATURE:
+                       DEG_id_tag_update(&obn->id, ID_RECALC_GEOMETRY);
+                       if (obn->pose)
+                               BKE_pose_tag_recalc(bmain, obn->pose);
+                       if (dupflag & USER_DUP_ARM) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data));
+                                       BKE_pose_rebuild(bmain, obn, obn->data, true);
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_LATTICE:
+                       if (dupflag != 0) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_lattice_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_CAMERA:
+                       if (dupflag != 0) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_camera_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_LIGHTPROBE:
+                       if (dupflag != 0) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_lightprobe_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_SPEAKER:
+                       if (dupflag != 0) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_speaker_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+               case OB_GPENCIL:
+                       if (dupflag != 0) {
+                               ID_NEW_REMAP_US2(obn->data)
+                               else {
+                                       obn->data = ID_NEW_SET(obn->data, BKE_gpencil_copy(bmain, obn->data));
+                                       didit = 1;
+                               }
+                               id_us_min(id);
+                       }
+                       break;
+       }
+
+       /* Check if obdata is copied. */
+       if (didit) {
+               Key *key = BKE_key_from_object(obn);
+
+               Key *oldkey = BKE_key_from_object(ob);
+               if (oldkey != NULL) {
+                       ID_NEW_SET(oldkey, key);
+               }
+
+               if (dupflag & USER_DUP_ACT) {
+                       BKE_animdata_copy_id_action(bmain, (ID *)obn->data, true);
+                       if (key) {
+                               BKE_animdata_copy_id_action(bmain, (ID *)key, true);
+                       }
+               }
+
+               if (dupflag & USER_DUP_MAT) {
+                       matarar = give_matarar(obn);
+                       if (matarar) {
+                               for (a = 0; a < obn->totcol; a++) {
+                                       id = (ID *)(*matarar)[a];
+                                       if (id) {
+                                               ID_NEW_REMAP_US((*matarar)[a])
+                                               else {
+                                                       (*matarar)[a] = ID_NEW_SET((*matarar)[a], BKE_material_copy(bmain, (*matarar)[a]));
+                                               }
+                                               id_us_min(id);
+                                       }
+                               }
+                       }
+               }
+       }
+
+#undef ID_NEW_REMAP_US
+#undef ID_NEW_REMAP_US2
+
+       BKE_libblock_relink_to_newid(&obn->id);
+
+       /* DAG_relations_tag_update(bmain); */ /* caller must do */
+
+       if (ob->data != NULL) {
+               DEG_id_tag_update_ex(bmain, (ID *)obn->data, ID_RECALC_EDITORS);
+       }
+
+       /* BKE_main_id_clear_newpoins(bmain); */ /* Called must do. */
+
+       return obn;
+}
+
 void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, const bool clear_proxy)
 {
        bool is_local = false, is_lib = false;
@@ -1565,7 +1787,7 @@ void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
 {
        /* paranoia checks */
        if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) {
-               printf("cannot make proxy\n");
+               CLOG_ERROR(&LOG, "cannot make proxy");
                return;
        }
 
@@ -1585,9 +1807,9 @@ void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
        if (cob) {
                ob->rotmode = target->rotmode;
                mul_m4_m4m4(ob->obmat, cob->obmat, target->obmat);
-               if (cob->dup_group) { /* should always be true */
+               if (cob->instance_collection) { /* should always be true */
                        float tvec[3];
-                       mul_v3_mat3_m4v3(tvec, ob->obmat, cob->dup_group->dupli_ofs);
+                       mul_v3_mat3_m4v3(tvec, ob->obmat, cob->instance_collection->instance_offset);
                        sub_v3_v3(ob->obmat[3], tvec);
                }
                BKE_object_apply_mat4(ob, ob->obmat, false, true);
@@ -1673,11 +1895,6 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size)
                        ob->empty_drawsize *= size;
                        break;
                }
-               case OB_GPENCIL:
-               {
-                       ob->empty_drawsize *= size;
-                       break;
-               }
                case OB_FONT:
                {
                        Curve *cu = ob->data;
@@ -1692,7 +1909,7 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size)
                }
                case OB_LAMP:
                {
-                       Lamp *lamp = ob->data;
+                       Light *lamp = ob->data;
                        lamp->dist *= size;
                        lamp->area_size  *= size;
                        lamp->area_sizey *= size;
@@ -1720,7 +1937,7 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size)
 void BKE_object_scale_to_mat3(Object *ob, float mat[3][3])
 {
        float vec[3];
-       mul_v3_v3v3(vec, ob->size, ob->dscale);
+       mul_v3_v3v3(vec, ob->scale, ob->dscale);
        size_to_mat3(mat, vec);
 }
 
@@ -1817,7 +2034,7 @@ void BKE_object_tfm_protected_backup(const Object *ob,
 
        TFMCPY3D(loc);
        TFMCPY3D(dloc);
-       TFMCPY3D(size);
+       TFMCPY3D(scale);
        TFMCPY3D(dscale);
        TFMCPY3D(rot);
        TFMCPY3D(drot);
@@ -1847,7 +2064,7 @@ void BKE_object_tfm_protected_restore(Object *ob,
                }
 
                if (protectflag & (OB_LOCK_SCALEX << i)) {
-                       ob->size[i] =  obtfm->size[i];
+                       ob->scale[i] =  obtfm->scale[i];
                        ob->dscale[i] = obtfm->dscale[i];
                }
 
@@ -1872,13 +2089,37 @@ void BKE_object_tfm_protected_restore(Object *ob,
        }
 }
 
+void BKE_object_tfm_copy(Object *object_dst, const Object *object_src)
+{
+#define TFMCPY(_v) (object_dst->_v = object_src->_v)
+#define TFMCPY3D(_v) copy_v3_v3(object_dst->_v, object_src->_v)
+#define TFMCPY4D(_v) copy_v4_v4(object_dst->_v, object_src->_v)
+
+       TFMCPY3D(loc);
+       TFMCPY3D(dloc);
+       TFMCPY3D(scale);
+       TFMCPY3D(dscale);
+       TFMCPY3D(rot);
+       TFMCPY3D(drot);
+       TFMCPY4D(quat);
+       TFMCPY4D(dquat);
+       TFMCPY3D(rotAxis);
+       TFMCPY3D(drotAxis);
+       TFMCPY(rotAngle);
+       TFMCPY(drotAngle);
+
+#undef TFMCPY
+#undef TFMCPY3D
+#undef TFMCPY4D
+}
+
 void BKE_object_to_mat3(Object *ob, float mat[3][3]) /* no parent */
 {
        float smat[3][3];
        float rmat[3][3];
        /*float q1[4];*/
 
-       /* size */
+       /* scale */
        BKE_object_scale_to_mat3(ob, smat);
 
        /* rot */
@@ -1915,8 +2156,7 @@ void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4])
  * \param depsgraph: Used for dupli-frame time.
  * \return success if \a mat is set.
  */
-static bool ob_parcurve(Object *ob, Object *par,
-                        float dupli_ctime, int dupli_transflag, float mat[4][4])
+static bool ob_parcurve(Object *ob, Object *par, float mat[4][4])
 {
        Curve *cu = par->data;
        float vec[4], dir[3], quat[4], radius, ctime;
@@ -1936,29 +2176,19 @@ static bool ob_parcurve(Object *ob, Object *par,
                return false;
        }
 
-       /* catch exceptions: curve paths used as a duplicator */
-       if ((dupli_transflag & OB_DUPLINOSPEED) == 0) {
-               /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated,
-                * but this will only work if it actually is animated...
-                *
-                * we divide the curvetime calculated in the previous step by the length of the path, to get a time
-                * factor, which then gets clamped to lie within 0.0 - 1.0 range
-                */
-               if (cu->pathlen) {
-                       ctime = cu->ctime / cu->pathlen;
-               }
-               else {
-                       ctime = cu->ctime;
-               }
-               CLAMP(ctime, 0.0f, 1.0f);
+       /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated,
+        * but this will only work if it actually is animated...
+        *
+        * we divide the curvetime calculated in the previous step by the length of the path, to get a time
+        * factor, which then gets clamped to lie within 0.0 - 1.0 range
+        */
+       if (cu->pathlen) {
+               ctime = cu->ctime / cu->pathlen;
        }
        else {
-               ctime = dupli_ctime;
-               if (cu->pathlen) {
-                       ctime /= cu->pathlen;
-               }
-               CLAMP(ctime, 0.0f, 1.0f);
+               ctime = cu->ctime;
        }
+       CLAMP(ctime, 0.0f, 1.0f);
 
        unit_m4(mat);
 
@@ -1994,7 +2224,7 @@ static void ob_parbone(Object *ob, Object *par, float mat[4][4])
        /* Make sure the bone is still valid */
        pchan = BKE_pose_channel_find_name(par->pose, ob->parsubstr);
        if (!pchan || !pchan->bone) {
-               printf("Object %s with Bone parent: bone %s doesn't exist\n", ob->id.name + 2, ob->parsubstr);
+               CLOG_ERROR(&LOG, "Object %s with Bone parent: bone %s doesn't exist", ob->id.name + 2, ob->parsubstr);
                unit_m4(mat);
                return;
        }
@@ -2021,7 +2251,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
 
        if (par->type == OB_MESH) {
                Mesh *me = par->data;
-               BMEditMesh *em = me->edit_btmesh;
+               BMEditMesh *em = me->edit_mesh;
                Mesh *me_eval = (em) ? em->mesh_eval_final : par->runtime.mesh_eval;
 
                if (me_eval) {
@@ -2078,9 +2308,8 @@ static void give_parvert(Object *par, int nr, float vec[3])
                        }
                }
                else {
-                       fprintf(stderr,
-                               "%s: Evaluated mesh is needed to solve parenting, "
-                               "object position can be wrong now\n", __func__);
+                       CLOG_ERROR(&LOG, "Evaluated mesh is needed to solve parenting, "
+                                  "object position can be wrong now");
                }
        }
        else if (ELEM(par->type, OB_CURVE, OB_SURF)) {
@@ -2145,9 +2374,7 @@ static void ob_parvert3(Object *ob, Object *par, float mat[4][4])
        }
 }
 
-void BKE_object_get_parent_matrix_for_dupli(Object *ob, Object *par,
-                                            float dupli_ctime, int dupli_transflag,
-                                            float parentmat[4][4])
+void BKE_object_get_parent_matrix(Object *ob, Object *par, float parentmat[4][4])
 {
        float tmat[4][4];
        float vec[3];
@@ -2158,7 +2385,7 @@ void BKE_object_get_parent_matrix_for_dupli(Object *ob, Object *par,
                        ok = 0;
                        if (par->type == OB_CURVE) {
                                if ((((Curve *)par->data)->flag & CU_PATH) &&
-                                   (ob_parcurve(ob, par, dupli_ctime, dupli_transflag, tmat)))
+                                   (ob_parcurve(ob, par, tmat)))
                                {
                                        ok = 1;
                                }
@@ -2188,20 +2415,13 @@ void BKE_object_get_parent_matrix_for_dupli(Object *ob, Object *par,
                        copy_m4_m4(parentmat, par->obmat);
                        break;
        }
-
-}
-
-void BKE_object_get_parent_matrix(Object *ob, Object *par, float parentmat[4][4])
-{
-       BKE_object_get_parent_matrix_for_dupli(ob, par, 0, 0, parentmat);
 }
 
 /**
  * \param r_originmat: Optional matrix that stores the space the object is in (without its own matrix applied)
  */
-static void solve_parenting(Object *ob, Object *par, float obmat[4][4], float slowmat[4][4],
-                            float r_originmat[3][3], const bool set_origin,
-                            float dupli_ctime, int dupli_transflag)
+static void solve_parenting(Object *ob, Object *par, float obmat[4][4],
+                            float r_originmat[3][3], const bool set_origin)
 {
        float totmat[4][4];
        float tmat[4][4];
@@ -2209,9 +2429,7 @@ static void solve_parenting(Object *ob, Object *par, float obmat[4][4], float sl
 
        BKE_object_to_mat4(ob, locmat);
 
-       if (ob->partype & PARSLOW) copy_m4_m4(slowmat, obmat);
-
-       BKE_object_get_parent_matrix_for_dupli(ob, par, dupli_ctime, dupli_transflag, totmat);
+       BKE_object_get_parent_matrix(ob, par, totmat);
 
        /* total */
        mul_m4_m4m4(tmat, totmat, ob->parentinv);
@@ -2225,59 +2443,24 @@ static void solve_parenting(Object *ob, Object *par, float obmat[4][4], float sl
        /* origin, for help line */
        if (set_origin) {
                if ((ob->partype & PARTYPE) == PARSKEL) {
-                       copy_v3_v3(ob->orig, par->obmat[3]);
+                       copy_v3_v3(ob->runtime.parent_display_origin, par->obmat[3]);
                }
                else {
-                       copy_v3_v3(ob->orig, totmat[3]);
+                       copy_v3_v3(ob->runtime.parent_display_origin, totmat[3]);
                }
        }
 }
 
-static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[4][4])
-{
-       float *fp1, *fp2;
-       float fac1, fac2;
-       int a;
-
-       /* include framerate */
-       fac1 = (1.0f / (1.0f + fabsf(ob->sf)));
-       if (fac1 >= 1.0f) return false;
-       fac2 = 1.0f - fac1;
-
-       fp1 = obmat[0];
-       fp2 = slowmat[0];
-       for (a = 0; a < 16; a++, fp1++, fp2++) {
-               fp1[0] = fac1 * fp1[0] + fac2 * fp2[0];
-       }
-
-       return true;
-}
-
 /* note, scene is the active scene while actual_scene is the scene the object resides in */
-void BKE_object_where_is_calc_time_ex(
-        Depsgraph *depsgraph, Scene *scene, Object *ob, float ctime, int dupli_transflag,
+static void object_where_is_calc_ex(
+        Depsgraph *depsgraph, Scene *scene, Object *ob, float ctime,
         RigidBodyWorld *rbw, float r_originmat[3][3])
 {
-       if (ob == NULL) return;
-
-       /* execute drivers only, as animation has already been done */
-       BKE_animsys_evaluate_animdata(depsgraph, scene, &ob->id, ob->adt, ctime, ADT_RECALC_DRIVERS);
-
        if (ob->parent) {
                Object *par = ob->parent;
-               float slowmat[4][4];
 
                /* calculate parent matrix */
-               solve_parenting(ob, par, ob->obmat, slowmat, r_originmat, true,
-                               ctime, dupli_transflag);
-
-               /* "slow parent" is definitely not threadsafe, and may also give bad results jumping around
-                * An old-fashioned hack which probably doesn't really cut it anymore
-                */
-               if (ob->partype & PARSLOW) {
-                       if (!where_is_object_parslow(ob, ob->obmat, slowmat))
-                               return;
-               }
+               solve_parenting(ob, par, ob->obmat, r_originmat, true);
        }
        else {
                BKE_object_to_mat4(ob, ob->obmat);
@@ -2303,32 +2486,20 @@ void BKE_object_where_is_calc_time_ex(
 
 void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *ob, float ctime)
 {
-       BKE_object_where_is_calc_time_ex(depsgraph, scene, ob, ctime, 0, NULL, NULL);
-}
-
-void BKE_object_where_is_calc_time_for_dupli(
-        Depsgraph *depsgraph, Scene *scene, struct Object *ob, float ctime, int dupli_transflag)
-{
-       BKE_object_where_is_calc_time_ex(depsgraph, scene, ob, ctime, dupli_transflag, NULL, NULL);
+       /* Execute drivers and animation. */
+       BKE_animsys_evaluate_animdata(depsgraph, scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
+       object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL);
 }
 
-
 /* get object transformation matrix without recalculating dependencies and
  * constraints -- assume dependencies are already solved by depsgraph.
  * no changes to object and it's parent would be done.
  * used for bundles orientation in 3d space relative to parented blender camera */
 void BKE_object_where_is_calc_mat4(Object *ob, float obmat[4][4])
 {
-
        if (ob->parent) {
-               float slowmat[4][4];
-
                Object *par = ob->parent;
-
-               solve_parenting(ob, par, obmat, slowmat, NULL, false, 0.0f, 0);
-
-               if (ob->partype & PARSLOW)
-                       where_is_object_parslow(ob, obmat, slowmat);
+               solve_parenting(ob, par, obmat, NULL, false);
        }
        else {
                BKE_object_to_mat4(ob, obmat);
@@ -2337,11 +2508,13 @@ void BKE_object_where_is_calc_mat4(Object *ob, float obmat[4][4])
 
 void BKE_object_where_is_calc_ex(Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
 {
-       BKE_object_where_is_calc_time_ex(depsgraph, scene, ob, DEG_get_ctime(depsgraph), 0, rbw, r_originmat);
+       float ctime = DEG_get_ctime(depsgraph);
+       object_where_is_calc_ex(depsgraph, scene, ob, ctime, rbw, r_originmat);
 }
 void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
 {
-       BKE_object_where_is_calc_time_ex(depsgraph, scene, ob, DEG_get_ctime(depsgraph), 0, NULL, NULL);
+       float ctime = DEG_get_ctime(depsgraph);
+       object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL);
 }
 
 /**
@@ -2354,7 +2527,6 @@ void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
  */
 void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *workob)
 {
-       Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
        BKE_object_workob_clear(workob);
 
        unit_m4(workob->obmat);
@@ -2364,17 +2536,17 @@ void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *o
        /* Since this is used while calculating parenting, at this moment ob_eval->parent is still NULL. */
        workob->parent = DEG_get_evaluated_object(depsgraph, ob->parent);
 
-       workob->trackflag = ob_eval->trackflag;
-       workob->upflag = ob_eval->upflag;
+       workob->trackflag = ob->trackflag;
+       workob->upflag = ob->upflag;
 
-       workob->partype = ob_eval->partype;
-       workob->par1 = ob_eval->par1;
-       workob->par2 = ob_eval->par2;
-       workob->par3 = ob_eval->par3;
+       workob->partype = ob->partype;
+       workob->par1 = ob->par1;
+       workob->par2 = ob->par2;
+       workob->par3 = ob->par3;
 
-       workob->constraints = ob_eval->constraints;
+       workob->constraints = ob->constraints;
 
-       BLI_strncpy(workob->parsubstr, ob_eval->parsubstr, sizeof(workob->parsubstr));
+       BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr));
 
        BKE_object_where_is_calc(depsgraph, scene, workob);
 }
@@ -2402,19 +2574,19 @@ void BKE_object_apply_mat4_ex(Object *ob, float mat[4][4], Object *parent, float
                mul_m4_m4m4(rmat, imat, mat); /* get the parent relative matrix */
 
                /* same as below, use rmat rather than mat */
-               mat4_to_loc_rot_size(ob->loc, rot, ob->size, rmat);
+               mat4_to_loc_rot_size(ob->loc, rot, ob->scale, rmat);
        }
        else {
-               mat4_to_loc_rot_size(ob->loc, rot, ob->size, mat);
+               mat4_to_loc_rot_size(ob->loc, rot, ob->scale, mat);
        }
 
        BKE_object_mat3_to_rot(ob, rot, use_compat);
 
        sub_v3_v3(ob->loc, ob->dloc);
 
-       if (ob->dscale[0] != 0.0f) ob->size[0] /= ob->dscale[0];
-       if (ob->dscale[1] != 0.0f) ob->size[1] /= ob->dscale[1];
-       if (ob->dscale[2] != 0.0f) ob->size[2] /= ob->dscale[2];
+       if (ob->dscale[0] != 0.0f) ob->scale[0] /= ob->dscale[0];
+       if (ob->dscale[1] != 0.0f) ob->scale[1] /= ob->dscale[1];
+       if (ob->dscale[2] != 0.0f) ob->scale[2] /= ob->dscale[2];
 
        /* BKE_object_mat3_to_rot handles delta rotations */
 }
@@ -2524,13 +2696,13 @@ void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval)
                zero_v3(max);
        }
 
-       if (ob->bb == NULL) {
-               ob->bb = MEM_callocN(sizeof(BoundBox), "DM-BoundBox");
+       if (ob->runtime.bb == NULL) {
+               ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "DM-BoundBox");
        }
 
-       BKE_boundbox_init_from_minmax(ob->bb, min, max);
+       BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
 
-       ob->bb->flag &= ~BOUNDBOX_DIRTY;
+       ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
 }
 
 void BKE_object_dimensions_get(Object *ob, float vec[3])
@@ -2567,7 +2739,7 @@ void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask)
                for (int i = 0; i < 3; i++) {
                        if (((1 << i) & axis_mask) == 0) {
                                if (len[i] > 0.0f) {
-                                       ob->size[i] = copysignf(value[i] / len[i], ob->size[i]);
+                                       ob->scale[i] = copysignf(value[i] / len[i], ob->scale[i]);
                                }
                        }
                }
@@ -2639,8 +2811,8 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
        if (changed == false) {
                float size[3];
 
-               copy_v3_v3(size, ob->size);
-               if ((ob->type == OB_EMPTY) || (ob->type == OB_GPENCIL)) {
+               copy_v3_v3(size, ob->scale);
+               if (ob->type == OB_EMPTY) {
                        mul_v3_fl(size, ob->empty_drawsize);
                }
 
@@ -2677,31 +2849,52 @@ void BKE_object_empty_draw_type_set(Object *ob, const int value)
        }
 }
 
-bool BKE_object_empty_image_is_visible_in_view3d(const Object *ob, const RegionView3D *rv3d)
+bool BKE_object_empty_image_frame_is_visible_in_view3d(const Object *ob, const RegionView3D *rv3d)
 {
-       char visibility_flag = ob->empty_image_visibility_flag;
+       const char visibility_flag = ob->empty_image_visibility_flag;
+       if (rv3d->is_persp) {
+               return (visibility_flag & OB_EMPTY_IMAGE_HIDE_PERSPECTIVE) == 0;
+       }
+       else {
+               return (visibility_flag & OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC) == 0;
+       }
+}
+
+bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const RegionView3D *rv3d)
+{
+       /* Caller is expected to check this. */
+       BLI_assert(BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d));
+
+       const char visibility_flag = ob->empty_image_visibility_flag;
 
        if ((visibility_flag & (OB_EMPTY_IMAGE_HIDE_BACK | OB_EMPTY_IMAGE_HIDE_FRONT)) != 0) {
-               /* TODO: this isn't correct with perspective projection. */
-               const float dot = dot_v3v3((float *)&ob->obmat[2], (float *)&rv3d->viewinv[2]);
+               float eps, dot;
+               if (rv3d->is_persp) {
+                       /* Note, we could normalize the 'view_dir' then use 'eps'
+                        * however the issue with empty objects being visible when viewed from the side
+                        * is only noticeable in orthographic views. */
+                       float view_dir[3];
+                       sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->obmat[3]);
+                       dot = dot_v3v3(ob->obmat[2], view_dir);
+                       eps = 0.0f;
+               }
+               else {
+                       dot = dot_v3v3(ob->obmat[2], rv3d->viewinv[2]);
+                       eps = 1e-5f;
+               }
                if (visibility_flag & OB_EMPTY_IMAGE_HIDE_BACK) {
-                       if (dot < 0.0f) {
+                       if (dot < eps) {
                                return false;
                        }
                }
                if (visibility_flag & OB_EMPTY_IMAGE_HIDE_FRONT) {
-                       if (dot > 0.0f) {
+                       if (dot > -eps) {
                                return false;
                        }
                }
        }
 
-       if (rv3d->is_persp) {
-               return (visibility_flag & OB_EMPTY_IMAGE_HIDE_PERSPECTIVE) == 0;
-       }
-       else {
-               return (visibility_flag & OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC) == 0;
-       }
+       return true;
 }
 
 bool BKE_object_minmax_dupli(Depsgraph *depsgraph, Scene *scene, Object *ob, float r_min[3], float r_max[3], const bool use_hidden)
@@ -2789,9 +2982,9 @@ void BKE_scene_foreach_display_point(
 
 /* copied from DNA_object_types.h */
 typedef struct ObTfmBack {
-       float loc[3], dloc[3], orig[3];
+       float loc[3], dloc[3];
        /** scale and delta scale. */
-       float size[3], dscale[3];
+       float scale[3], dscale[3];
        /** euler rotation. */
        float rot[3], drot[3];
        /** quaternion rotation. */
@@ -2815,8 +3008,7 @@ void *BKE_object_tfm_backup(Object *ob)
        ObTfmBack *obtfm = MEM_mallocN(sizeof(ObTfmBack), "ObTfmBack");
        copy_v3_v3(obtfm->loc, ob->loc);
        copy_v3_v3(obtfm->dloc, ob->dloc);
-       copy_v3_v3(obtfm->orig, ob->orig);
-       copy_v3_v3(obtfm->size, ob->size);
+       copy_v3_v3(obtfm->scale, ob->scale);
        copy_v3_v3(obtfm->dscale, ob->dscale);
        copy_v3_v3(obtfm->rot, ob->rot);
        copy_v3_v3(obtfm->drot, ob->drot);
@@ -2839,8 +3031,7 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
        ObTfmBack *obtfm = (ObTfmBack *)obtfm_pt;
        copy_v3_v3(ob->loc, obtfm->loc);
        copy_v3_v3(ob->dloc, obtfm->dloc);
-       copy_v3_v3(ob->orig, obtfm->orig);
-       copy_v3_v3(ob->size, obtfm->size);
+       copy_v3_v3(ob->scale, obtfm->scale);
        copy_v3_v3(ob->dscale, obtfm->dscale);
        copy_v3_v3(ob->rot, obtfm->rot);
        copy_v3_v3(ob->drot, obtfm->drot);
@@ -3577,6 +3768,18 @@ bool BKE_object_is_animated(Scene *scene, Object *ob)
        return false;
 }
 
+/** Return the number of scenes using (instantiating) that object in their collections. */
+int BKE_object_scenes_users_get(Main *bmain, Object *ob)
+{
+       int num_scenes = 0;
+       for (Scene *scene = bmain->scene.first; scene != NULL; scene = scene->id.next) {
+               if (BKE_collection_has_object_recursive(BKE_collection_master(scene), ob)) {
+                       num_scenes++;
+               }
+       }
+       return num_scenes;
+}
+
 MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default)
 {
        MovieClip *clip = use_default ? scene->clip : NULL;
@@ -3608,7 +3811,7 @@ void BKE_object_runtime_reset(Object *object)
 }
 
 /* Reset all pointers which we don't want to be shared when copying the object. */
-void BKE_object_runtime_reset_on_copy(Object *object)
+void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
 {
        Object_Runtime *runtime = &object->runtime;
        runtime->mesh_eval = NULL;
@@ -4081,16 +4284,17 @@ bool BKE_object_modifier_update_subframe(
        /* was originally ID_RECALC_ALL - TODO - which flags are really needed??? */
        /* TODO(sergey): What about animation? */
        ob->id.recalc |= ID_RECALC_ALL;
-       BKE_animsys_evaluate_animdata(depsgraph, scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
        if (update_mesh) {
+               BKE_animsys_evaluate_animdata(depsgraph, scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
                /* ignore cache clear during subframe updates
                 * to not mess up cache validity */
                object_cacheIgnoreClear(ob, 1);
                BKE_object_handle_update(depsgraph, scene, ob);
                object_cacheIgnoreClear(ob, 0);
        }
-       else
+       else {
                BKE_object_where_is_calc_time(depsgraph, scene, ob, frame);
+       }
 
        /* for curve following objects, parented curve has to be updated too */
        if (ob->type == OB_CURVE) {