Merge branch 'master' into blender2.8
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 15 Dec 2017 09:45:20 +0000 (10:45 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 15 Dec 2017 09:45:20 +0000 (10:45 +0100)
17 files changed:
1  2 
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/group.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_legacy.c
source/blender/depsgraph/intern/builder/deg_builder.cc
source/blender/depsgraph/intern/depsgraph.cc
source/blender/depsgraph/intern/depsgraph_tag.cc
source/blender/depsgraph/intern/eval/deg_eval_flush.cc
source/blender/editors/render/render_update.c
source/blender/makesdna/DNA_ID.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_text_types.h
source/blender/makesrna/intern/rna_ID.c
source/blender/modifiers/intern/MOD_correctivesmooth.c

index 0394c813a14edcb7b5fe43e5cb9bdaeb9b21a76b,6dc8cc5aff1c30ddfaa8049e276232ff3c6576bf..5b55433c1b9be73872d7023f7724e676bf288728
@@@ -372,45 -367,12 +372,45 @@@ void BKE_group_handle_recalc_and_update
  #endif
        {
                /* only do existing tags, as set by regular depsgraph */
 -              for (go = group->gobject.first; go; go = go->next) {
 -                      if (go->ob) {
 -                              if (go->ob->recalc) {
 -                                      BKE_object_handle_update(eval_ctx, scene, go->ob);
 -                              }
 +              FOREACH_GROUP_OBJECT(group, object)
 +              {
-                       if (object->id.tag & LIB_TAG_ID_RECALC_ALL) {
++                      if (object->id.recalc & ID_RECALC_ALL) {
 +                              BKE_object_handle_update(eval_ctx, scene, object);
                        }
                }
 +              FOREACH_GROUP_OBJECT_END
        }
  }
 +
 +/* ******** Dependency graph evaluation ******** */
 +
 +static void group_eval_layer_collections(
 +        const struct EvaluationContext *eval_ctx,
 +        Group *group,
 +        ListBase *layer_collections,
 +        LayerCollection *parent_layer_collection)
 +{
 +      LINKLIST_FOREACH (LayerCollection *, layer_collection, layer_collections) {
 +              /* Evaluate layer collection itself. */
 +              BKE_layer_eval_layer_collection(eval_ctx,
 +                                              layer_collection,
 +                                              parent_layer_collection);
 +              /* Evaluate nested collections. */
 +              group_eval_layer_collections(eval_ctx,
 +                                           group,
 +                                           &layer_collection->layer_collections,
 +                                           layer_collection);
 +      }
 +}
 +
 +void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx,
 +                                Group *group)
 +{
 +      DEBUG_PRINT("%s on %s (%p)\n", __func__, group->id.name, group);
 +      BKE_layer_eval_layer_collection_pre(eval_ctx, &group->id, group->view_layer);
 +      group_eval_layer_collections(eval_ctx,
 +                                   group,
 +                                   &group->view_layer->layer_collections,
 +                                   NULL);
 +      BKE_layer_eval_layer_collection_post(eval_ctx, group->view_layer);
 +}
index 717d395fc68d3b1b1a8765555709bc35e20156f9,c6b4e3fb0c752c2f80957b13a9d801758df6e598..66c87ac7a5c8b920bbe722f472071b84874384b0
@@@ -2699,12 -2621,7 +2699,12 @@@ void BKE_object_handle_update_ex(const 
                                   RigidBodyWorld *rbw,
                                   const bool do_proxy_update)
  {
 -      if ((ob->recalc & OB_RECALC_ALL) == 0) {
 +      const ID *object_data = ob->data;
-       const bool recalc_object = (ob->id.tag & LIB_TAG_ID_RECALC) != 0;
++      const bool recalc_object = (ob->id.recalc & ID_RECALC) != 0;
 +      const bool recalc_data =
-               (object_data != NULL) ? ((object_data->tag & LIB_TAG_ID_RECALC_ALL) != 0)
++              (object_data != NULL) ? ((object_data->recalc & ID_RECALC_ALL) != 0)
 +                                    : 0;
 +      if (!recalc_object && ! recalc_data) {
                object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update);
                return;
        }
                BKE_object_handle_data_update(eval_ctx, scene, ob);
        }
  
-       ob->id.tag &= ~LIB_TAG_ID_RECALC_ALL;
 -      ob->recalc &= ~OB_RECALC_ALL;
++      ob->id.recalc &= ID_RECALC_ALL;
  
        object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update);
  }
@@@ -3724,8 -3655,7 +3724,8 @@@ bool BKE_object_modifier_update_subfram
        }
  
        /* was originally OB_RECALC_ALL - TODO - which flags are really needed??? */
 -      ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
 +      /* TODO(sergey): What about animation? */
-       ob->id.tag |= LIB_TAG_ID_RECALC_ALL;
++      ob->id.recalc |= ID_RECALC_ALL;
        BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
        if (update_mesh) {
                /* ignore cache clear during subframe updates
index 156a6e3d1c07c612c32a1e2917b6bd8952505c63,ad37679800b3ba4eec5d59942ee4ca41786cfade..39ece4fd1430352e67e6774354b571b13f9dd7c6
@@@ -1871,7 -1944,7 +1871,7 @@@ void blo_do_versions_pre250(FileData *f
                                        BKE_pose_tag_recalc(main, ob->pose);
  
                                /* cannot call stuff now (pointers!), done in setup_app_data */
-                               ob->id.tag |= LIB_TAG_ID_RECALC_ALL;
 -                              ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
++                              ob->id.recalc |= ID_RECALC_ALL;
  
                                /* new generic xray option */
                                arm = blo_do_versions_newlibadr(fd, lib, ob->data);
index 20a93673350967139b079568744de08cfc55eeac,26f729a16d769838d7c2429ff6e0cc23390eaa47..1e906d454acceb6d15dae3d2f427751a2d1a546d
  
  namespace DEG {
  
 -static bool check_object_needs_evaluation(Object *object)
 -{
 -      if (object->recalc & OB_RECALC_ALL) {
 -              /* Object is tagged for update anyway, no need to re-tag it. */
 -              return false;
 -      }
 -      if (object->type == OB_MESH) {
 -              return object->derivedFinal == NULL;
 -      }
 -      else if (ELEM(object->type,
 -                    OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
 -      {
 -              return object->curve_cache == NULL;
 -      }
 -      return false;
 -}
 -
 -void deg_graph_build_flush_layers(Depsgraph *graph)
 -{
 -      BLI_Stack *stack = BLI_stack_new(sizeof(OperationDepsNode *),
 -                                       "DEG flush layers stack");
 -      foreach (OperationDepsNode *node, graph->operations) {
 -              IDDepsNode *id_node = node->owner->owner;
 -              node->done = 0;
 -              node->num_links_pending = 0;
 -              foreach (DepsRelation *rel, node->outlinks) {
 -                      if ((rel->from->type == DEG_NODE_TYPE_OPERATION) &&
 -                          (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
 -                      {
 -                              ++node->num_links_pending;
 -                      }
 -              }
 -              if (node->num_links_pending == 0) {
 -                      BLI_stack_push(stack, &node);
 -                      node->done = 1;
 -              }
 -              node->owner->layers = id_node->layers;
 -              id_node->id->tag |= LIB_TAG_DOIT;
 -      }
 -      while (!BLI_stack_is_empty(stack)) {
 -              OperationDepsNode *node;
 -              BLI_stack_pop(stack, &node);
 -              /* Flush layers to parents. */
 -              foreach (DepsRelation *rel, node->inlinks) {
 -                      if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
 -                              OperationDepsNode *from = (OperationDepsNode *)rel->from;
 -                              from->owner->layers |= node->owner->layers;
 -                      }
 -              }
 -              /* Schedule parent nodes. */
 -              foreach (DepsRelation *rel, node->inlinks) {
 -                      if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
 -                              OperationDepsNode *from = (OperationDepsNode *)rel->from;
 -                              if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
 -                                      BLI_assert(from->num_links_pending > 0);
 -                                      --from->num_links_pending;
 -                              }
 -                              if (from->num_links_pending == 0 && from->done == 0) {
 -                                      BLI_stack_push(stack, &from);
 -                                      from->done = 1;
 -                              }
 -                      }
 -              }
 -      }
 -      BLI_stack_free(stack);
 -}
 -
 -void deg_graph_build_finalize(Depsgraph *graph)
 +void deg_graph_build_finalize(Main *bmain, Depsgraph *graph)
  {
 -      /* STEP 1: Make sure new invisible dependencies are ready for use.
 -       *
 -       * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
 -       * to do it ahead of a time and don't spend time on flushing updates on
 -       * every frame change.
 -       */
 -      GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
 -      {
 -              if (id_node->layers == 0) {
 -                      ID *id = id_node->id;
 -                      if (GS(id->name) == ID_OB) {
 -                              Object *object = (Object *)id;
 -                              if (check_object_needs_evaluation(object)) {
 -                                      id_node->tag_update(graph);
 -                              }
 -                      }
 -              }
 -      }
 -      GHASH_FOREACH_END();
 -      /* STEP 2: Flush visibility layers from children to parent. */
 -      deg_graph_build_flush_layers(graph);
 -      /* STEP 3: Re-tag IDs for update if it was tagged before the relations
 +      const bool use_copy_on_write = DEG_depsgraph_use_copy_on_write();
 +      /* Re-tag IDs for update if it was tagged before the relations
         * update tag.
         */
 -      GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
 -      {
 -              GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp, id_node->components)
 -              {
 -                      id_node->layers |= comp->layers;
 +      foreach (IDDepsNode *id_node, graph->id_nodes) {
 +              ID *id = id_node->id_orig;
 +              id_node->finalize_build(graph);
-               if ((id->tag & LIB_TAG_ID_RECALC_ALL)) {
++              if ((id->recalc & ID_RECALC_ALL)) {
 +                      id_node->tag_update(graph);
                }
 -              GHASH_FOREACH_END();
 -
 -              if ((id_node->layers & graph->layers) != 0 || graph->layers == 0) {
 -                      ID *id = id_node->id;
 -                      if ((id->recalc & ID_RECALC_ALL) &&
 -                          (id->tag & LIB_TAG_DOIT))
 -                      {
 -                              id_node->tag_update(graph);
 -                              id->tag &= ~LIB_TAG_DOIT;
 -                      }
 -                      else if (GS(id->name) == ID_OB) {
 -                              Object *object = (Object *)id;
 -                              if (object->recalc & OB_RECALC_ALL) {
 -                                      id_node->tag_update(graph);
 -                                      id->tag &= ~LIB_TAG_DOIT;
 -                              }
 -                      }
 +              /* TODO(sergey): This is not ideal at all, since this forces
 +               * re-evaluaiton of the whole tree.
 +               */
 +              if (use_copy_on_write) {
 +                      DEG_id_tag_update_ex(bmain, id_node->id_orig, DEG_TAG_COPY_ON_WRITE);
                }
 -              id_node->finalize_build();
        }
 -      GHASH_FOREACH_END();
  }
  
  }  // namespace DEG
index 4fea8b49706eb872a4b8884e0924b071ccbf54b9,dd7284eb629f798e4ba1b73935bb5cef60e3ecab..1227db4c1bb98ad69723f90af896f3bb638550a3
@@@ -354,7 -312,7 +354,7 @@@ DepsRelation *Depsgraph::add_new_relati
        if (comp_node->type == DEG_NODE_TYPE_GEOMETRY) {
                IDDepsNode *id_to = to->owner->owner;
                IDDepsNode *id_from = from->owner->owner;
-               if (id_to != id_from && (id_to->id_orig->tag & LIB_TAG_ID_RECALC_ALL)) {
 -              if (id_to != id_from && (id_to->id->recalc & ID_RECALC_ALL)) {
++              if (id_to != id_from && (id_to->id_orig->recalc & ID_RECALC_ALL)) {
                        if ((id_from->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
                                id_from->tag_update(this);
                                id_from->eval_flags |= DAG_EVAL_NEED_CPU;
index fecc9a75a14895e2fb589304a09d2cebf52c19d0,107bbda1030df405743fb2171be857091b02c4c8..c285efd58195f5f592856c60f16909e55603b4f0
@@@ -66,155 -60,39 +66,155 @@@ enum 
        COMPONENT_STATE_DONE      = 2,
  };
  
 +typedef std::deque<OperationDepsNode *> FlushQueue;
 +
  namespace {
  
 -// TODO(sergey): De-duplicate with depsgraph_tag,cc
 -void lib_id_recalc_tag(Main *bmain, ID *id)
 +void flush_init_operation_node_func(void *data_v, int i)
  {
 -      id->recalc |= ID_RECALC;
 -      DEG_id_type_tag(bmain, GS(id->name));
 +      Depsgraph *graph = (Depsgraph *)data_v;
 +      OperationDepsNode *node = graph->operations[i];
 +      node->scheduled = false;
  }
  
 -void lib_id_recalc_data_tag(Main *bmain, ID *id)
 +void flush_init_id_node_func(void *data_v, int i)
  {
 -      id->recalc |= ID_RECALC_DATA;
 -      DEG_id_type_tag(bmain, GS(id->name));
 +      Depsgraph *graph = (Depsgraph *)data_v;
 +      IDDepsNode *id_node = graph->id_nodes[i];
 +      id_node->done = ID_STATE_NONE;
 +      GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
 +              comp_node->done = COMPONENT_STATE_NONE;
 +      GHASH_FOREACH_END();
  }
  
 -}  /* namespace */
 +BLI_INLINE void flush_prepare(Depsgraph *graph)
 +{
 +      const int num_operations = graph->operations.size();
 +      BLI_task_parallel_range(0, num_operations,
 +                              graph,
 +                              flush_init_operation_node_func,
 +                              (num_operations > 256));
 +      const int num_id_nodes = graph->id_nodes.size();
 +      BLI_task_parallel_range(0, num_id_nodes,
 +                              graph,
 +                              flush_init_id_node_func,
 +                              (num_id_nodes > 256));
 +}
  
 -typedef std::deque<OperationDepsNode *> FlushQueue;
 +BLI_INLINE void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue)
 +{
 +      GSET_FOREACH_BEGIN(OperationDepsNode *, op_node, graph->entry_tags)
 +      {
 +              queue->push_back(op_node);
 +              op_node->scheduled = true;
 +      }
 +      GSET_FOREACH_END();
 +}
  
 -static void flush_init_func(void *data_v, int i)
 +BLI_INLINE void flush_handle_id_node(IDDepsNode *id_node)
  {
 -      /* ID node's done flag is used to avoid multiple editors update
 -       * for the same ID.
 +      id_node->done = ID_STATE_MODIFIED;
 +}
 +
 +/* TODO(sergey): We can reduce number of arguments here. */
 +BLI_INLINE void flush_handle_component_node(Depsgraph *graph,
 +                                            IDDepsNode *id_node,
 +                                            ComponentDepsNode *comp_node,
 +                                            bool use_copy_on_write,
 +                                            FlushQueue *queue)
 +{
 +      /* We only handle component once. */
 +      if (comp_node->done == COMPONENT_STATE_DONE) {
 +              return;
 +      }
 +      comp_node->done = COMPONENT_STATE_DONE;
 +      /* Currently this is needed to get object->mesh to be replaced with
 +       * original mesh (rather than being evaluated_mesh).
 +       *
 +       * TODO(sergey): This is something we need to avoid.
         */
 -      Depsgraph *graph = (Depsgraph *)data_v;
 -      OperationDepsNode *node = graph->operations[i];
 -      ComponentDepsNode *comp_node = node->owner;
 -      IDDepsNode *id_node = comp_node->owner;
 -      id_node->done = 0;
 -      comp_node->done = COMPONENT_STATE_NONE;
 -      node->scheduled = false;
 +      if (use_copy_on_write && comp_node->depends_on_cow()) {
 +              ComponentDepsNode *cow_comp =
 +                      id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
 +              cow_comp->tag_update(graph);
 +      }
 +      /* Tag all required operations in component for update.  */
 +      foreach (OperationDepsNode *op, comp_node->operations) {
 +              /* We don't want to flush tags in "upstream" direction for
 +               * certain types of operations.
 +               *
 +               * TODO(sergey): Need a more generic solution for this.
 +               */
 +              if (op->opcode == DEG_OPCODE_PARTICLE_SETTINGS_EVAL) {
 +                      continue;
 +              }
 +              op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
 +      }
 +      /* When some target changes bone, we might need to re-run the
 +       * whole IK solver, otherwise result might be unpredictable.
 +       */
 +      if (comp_node->type == DEG_NODE_TYPE_BONE) {
 +              ComponentDepsNode *pose_comp =
 +                      id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
 +              BLI_assert(pose_comp != NULL);
 +              if (pose_comp->done == COMPONENT_STATE_NONE) {
 +                      queue->push_front(pose_comp->get_entry_operation());
 +                      pose_comp->done = COMPONENT_STATE_SCHEDULED;
 +              }
 +      }
 +}
 +
 +/* Schedule children of the given operation node for traversal.
 + *
 + * One of the children will by-pass the queue and will be returned as a function
 + * return value, so it can start being handled right away, without building too
 + * much of a queue.
 + */
 +BLI_INLINE OperationDepsNode *flush_schedule_children(
 +        OperationDepsNode *op_node,
 +        FlushQueue *queue)
 +{
 +      OperationDepsNode *result = NULL;
 +      foreach (DepsRelation *rel, op_node->outlinks) {
 +              OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
 +              if (to_node->scheduled == false) {
 +                      if (result != NULL) {
 +                              queue->push_front(to_node);
 +                      }
 +                      else {
 +                              result = to_node;
 +                      }
 +                      to_node->scheduled = true;
 +              }
 +      }
 +      return result;
  }
  
-               id_cow->tag |= (id_orig->tag & LIB_TAG_ID_RECALC_ALL);
 +BLI_INLINE void flush_editors_id_update(Main *bmain,
 +                                        Depsgraph *graph,
 +                                        const DEGEditorUpdateContext *update_ctx)
 +{
 +      foreach (IDDepsNode *id_node, graph->id_nodes) {
 +              if (id_node->done != ID_STATE_MODIFIED) {
 +                      continue;
 +              }
 +              /* TODO(sergey): Do we need to pass original or evaluated ID here? */
 +              ID *id_orig = id_node->id_orig;
 +              ID *id_cow = id_node->id_cow;
 +              /* Copy tag from original data to CoW storage.
 +               * This is because DEG_id_tag_update() sets tags on original
 +               * data.
 +               */
++              id_cow->tag |= (id_orig->recalc & ID_RECALC_ALL);
 +              if (deg_copy_on_write_is_expanded(id_cow)) {
 +                      deg_editors_id_update(update_ctx, id_cow);
 +              }
 +              lib_id_recalc_tag(bmain, id_orig);
 +      }
 +}
 +
 +}  // namespace
 +
  /* Flush updates from tagged nodes outwards until all affected nodes
   * are tagged.
   */
index a391b13a00089bccdd117e2208eb500ca554b90c,4e02ff77a3175fb7faec95abd43887e14768d2b4..421096621298c2b69b5abf7cc9ace57b0fe2ce8e
@@@ -309,11 -295,8 +309,11 @@@ static void material_changed(Main *bmai
        BKE_icon_changed(BKE_icon_id_ensure(&ma->id));
  
        /* glsl */
-       if (ma->id.tag & LIB_TAG_ID_RECALC) {
 -      if (ma->gpumaterial.first)
 -              GPU_material_free(&ma->gpumaterial);
++      if (ma->id.recalc & ID_RECALC) {
 +              if (!BLI_listbase_is_empty(&ma->gpumaterial)) {
 +                      GPU_material_free(&ma->gpumaterial);
 +              }
 +      }
  
        /* find node materials using this */
        for (parent = bmain->mat.first; parent; parent = parent->id.next) {
@@@ -484,23 -468,23 +484,23 @@@ static void texture_changed(Main *bmain
        }
  }
  
 -static void world_changed(Main *bmain, World *wo)
 +static void world_changed(Main *UNUSED(bmain), World *wo)
  {
 -      Material *ma;
 -
        /* icons */
        BKE_icon_changed(BKE_icon_id_ensure(&wo->id));
 -      
 -      /* glsl */
 -      for (ma = bmain->mat.first; ma; ma = ma->id.next)
 -              if (ma->gpumaterial.first)
 -                      GPU_material_free(&ma->gpumaterial);
  
 -      if (defmaterial.gpumaterial.first)
 -              GPU_material_free(&defmaterial.gpumaterial);
 -      
 -      if (wo->gpumaterial.first)
 -              GPU_material_free(&wo->gpumaterial);
 +      /* XXX temporary flag waiting for depsgraph proper tagging */
 +      wo->update_flag = 1;
 +
 +      /* glsl */
-       if (wo->id.tag & LIB_TAG_ID_RECALC) {
++      if (wo->id.recalc & ID_RECALC) {
 +              if (!BLI_listbase_is_empty(&defmaterial.gpumaterial)) {
 +                      GPU_material_free(&defmaterial.gpumaterial);
 +              }
 +              if (!BLI_listbase_is_empty(&wo->gpumaterial)) {
 +                      GPU_material_free(&wo->gpumaterial);
 +              }
 +      }
  }
  
  static void image_changed(Main *bmain, Image *ima)
index 6f08afd0fe42b29c41a03f840683ece1f4d9595c,c1c4d6c5376c4d3915f2f730c037d6f64a619294..78624e17d7333c29d86c4784514a84d40050c175
@@@ -211,13 -130,11 +211,14 @@@ typedef struct ID 
        int tag;
        int us;
        int icon_id;
+       int recalc;
+       int pad;
        IDProperty *properties;
  
 +      IDOverrideStatic *override_static;  /* Reference linked ID which this one overrides. */
++      void *pad1;
 +
        void *py_instance;
-       void *pad1;
  } ID;
  
  /**
@@@ -437,22 -348,20 +438,24 @@@ enum 
        /* RESET_AFTER_USE tag existing data before linking so we know what is new. */
        LIB_TAG_PRE_EXISTING    = 1 << 11,
  
-       /* RESET_AFTER_USE, used by update code (depsgraph). */
-       LIB_TAG_ID_RECALC       = 1 << 12,
-       /* LIB_TAG_AVAILABLE  = 1 << 13, */  /* Was used by deprecated flag. */
-       /* LIB_TAG_AVAILABLE  = 1 << 14, */  /* Was used by deprecated flag. */
-       LIB_TAG_ID_RECALC_ALL   = (LIB_TAG_ID_RECALC),
 +      /* The datablock is a copy-on-write version. */
-       LIB_TAG_COPY_ON_WRITE   = 1 << 15,
-       LIB_TAG_COPY_ON_WRITE_EVAL = 1 << 16,
++      LIB_TAG_COPY_ON_WRITE   = 1 << 12,
++      LIB_TAG_COPY_ON_WRITE_EVAL = 1 << 13,
 +
        /* RESET_NEVER tag datablock for freeing etc. behavior (usually set when copying real one into temp/runtime one). */
-       LIB_TAG_NO_MAIN          = 1 << 17,  /* Datablock is not listed in Main database. */
-       LIB_TAG_NO_USER_REFCOUNT = 1 << 18,  /* Datablock does not refcount usages of other IDs. */
 -      LIB_TAG_NO_MAIN          = 1 << 11,  /* Datablock is not listed in Main database. */
 -      LIB_TAG_NO_USER_REFCOUNT = 1 << 13,  /* Datablock does not refcount usages of other IDs. */
++      LIB_TAG_NO_MAIN          = 1 << 14,  /* Datablock is not listed in Main database. */
++      LIB_TAG_NO_USER_REFCOUNT = 1 << 15,  /* Datablock does not refcount usages of other IDs. */
        /* Datablock was not allocated by standard system (BKE_libblock_alloc), do not free its memory
         * (usual type-specific freeing is called though). */
-       LIB_TAG_NOT_ALLOCATED     = 1 << 19,
 -      LIB_TAG_NOT_ALLOCATED     = 1 << 14,
++      LIB_TAG_NOT_ALLOCATED     = 1 << 16,
+ };
+ enum {
+       /* RESET_AFTER_USE, used by update code (depsgraph). */
+       ID_RECALC       = 1 << 0,
+       ID_RECALC_DATA  = 1 << 1,
+       ID_RECALC_SKIP_ANIM_TAG  = 1 << 2,
+       ID_RECALC_ALL   = (ID_RECALC | ID_RECALC_DATA),
  };
  
  /* To filter ID types (filter_id) */
index 78c623f6408b8a218c4c669f808de71b14a615b3,a9c36007d9c2aa65189058304977f21212ea80c1..79cf5040d9e1cc007022192ff4dbdd560d1ec93d
@@@ -276,10 -254,8 +277,8 @@@ typedef struct Object 
        int gameflag;
        int gameflag2;
  
-       struct BulletSoftBody *bsoft;   /* settings for game engine bullet soft body */
        char restrictflag;              /* for restricting view, select, render etc. accessible in outliner */
 -      char recalc;                    /* dependency flag */
 +      char pad3;
        short softflag;                 /* softbody settings */
        float anisotropicFriction[3];
  
  
        struct FluidsimSettings *fluidsimSettings; /* if fluidsim enabled, store additional settings */
  
 -      /* Runtime valuated curve-specific data, not stored in the file */
 -      struct CurveCache *curve_cache;
 -
        struct DerivedMesh *derivedDeform, *derivedFinal;
++      void *pad7;
        uint64_t lastDataMask;   /* the custom data layer mask that was last used to calculate derivedDeform and derivedFinal */
        uint64_t customdata_mask; /* (extra) custom data layer mask to use for creating derivedmesh, set by depsgraph */
        unsigned int state;                     /* bit masks of game controllers that are active */
  
        float ima_ofs[2];               /* offset for image empties */
        ImageUser *iuser;               /* must be non-null when oject is an empty image */
 -      void *pad3;
++      void *pad4;
  
        ListBase lodlevels;             /* contains data for levels of detail */
        LodLevel *currentlod;
  
        struct PreviewImage *preview;
-       int pad1;
 +
 +      struct IDProperty *base_collection_properties; /* used by depsgraph, flushed from base */
 +
 +      ListBase drawdata;              /* runtime, ObjectEngineData */
++      int pad6;
 +      int select_color;
 +
 +      /* Mesh structure createrd during object evaluaiton.
 +       * It has all modifiers applied.
 +       */
 +      struct Mesh *mesh_evaluated;
  } Object;
  
  /* Warning, this is not used anymore because hooks are now modifiers */
index d25391ca95d9c10b1fbd50e723c2d789d0834217,c9d4a8a5ca3208cf05e8517ee1c5f50b6e35b663..065ee801b843b5ec39df80840a6039544aed5236
@@@ -1673,11 -1685,6 +1676,7 @@@ typedef struct Scene 
        uint64_t customdata_mask;       /* XXX. runtime flag for drawing, actually belongs in the window, only used by BKE_object_handle_update() */
        uint64_t customdata_mask_modal; /* XXX. same as above but for temp operator use (gl renders) */
  
-       /* Movie Tracking */
-       struct MovieClip *clip;                 /* active movie clip */
 +
        /* Color Management */
        ColorManagedViewSettings view_settings;
        ColorManagedDisplaySettings display_settings;
index c7969cd30e787e5673f11b535a6c4a9c501ed7b2,17ef098a3bb02f111473680143d23400248386e3..0a9b8c320b5a93cad26756ee4ff8aa970ea63212
@@@ -59,10 -60,10 +60,10 @@@ typedef struct Text 
        int curc, selc;
        
        char *undo_buf;
+       void *pad;
        int undo_pos, undo_len;
--      
++
        double mtime;
-       void *compiled;
  } Text;
  
  #define TXT_TABSIZE   4
index c7446b5674a974bb80236fb5237145c3137c69d9,a9e34247cbd6614563c4b46b994ba70021b36d70..cd7e339a2d7cb36c0a5e3af62c337af2dc93c897
@@@ -772,28 -754,6 +772,28 @@@ static PointerRNA rna_IDPreview_get(Poi
        return rna_pointer_inherit_refine(ptr, &RNA_ImagePreview, prv_img);
  }
  
-       return ((data->tag & LIB_TAG_ID_RECALC_ALL) != 0);
 +static int rna_ID_is_updated_data_get(PointerRNA *ptr)
 +{
 +      ID *id = (ID *)ptr->data;
 +      if (GS(id->name) != ID_OB) {
 +              return 0;
 +      }
 +      Object *object = (Object *)id;
 +      ID *data = object->data;
 +      if (data == NULL) {
 +              return 0;
 +      }
++      return ((data->recalc & ID_RECALC_ALL) != 0);
 +}
 +
 +static PointerRNA rna_ID_override_reference_get(PointerRNA *ptr)
 +{
 +      ID *id = (ID *)ptr->data;
 +      ID *reference = (id && id->override_static) ? id->override_static->reference : NULL;
 +
 +      return reference ? rna_pointer_inherit_refine(ptr, ID_code_to_RNA_type(GS(reference->name)), reference) : PointerRNA_NULL;
 +}
 +
  #else
  
  static void rna_def_ID_properties(BlenderRNA *brna)
@@@ -1042,8 -1002,8 +1042,9 @@@ static void rna_def_ID(BlenderRNA *brna
        RNA_def_property_ui_text(prop, "Is Updated", "Data-block is tagged for recalculation");
  
        prop = RNA_def_property(srna, "is_updated_data", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "recalc", ID_RECALC_DATA);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 +      RNA_def_property_boolean_funcs(prop, "rna_ID_is_updated_data_get", NULL);
        RNA_def_property_ui_text(prop, "Is Updated Data", "Data-block data is tagged for recalculation");
  
        prop = RNA_def_property(srna, "is_library_indirect", PROP_BOOLEAN, PROP_NONE);