diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index c5eefedcfad..ff05ffc8df7 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -247,7 +247,7 @@ void BKE_object_data_select_update( void BKE_object_eval_flush_base_flags( const struct EvaluationContext *eval_ctx, - struct Object *object, struct Base *base, + struct Object *object, int base_index, const bool is_from_set); void BKE_object_handle_data_update( diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 4d3b4e43043..50c7dc0c02f 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -216,6 +216,8 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user) MEM_freeN(view_layer->id_properties); } + MEM_SAFE_FREE(view_layer->object_bases_array); + MEM_freeN(view_layer); } @@ -503,6 +505,8 @@ void BKE_view_layer_copy_data( view_layer_dst->basact = base_dst; } } + + view_layer_dst->object_bases_array = NULL; } /** @@ -2358,11 +2362,19 @@ static void layer_eval_layer_collection(const EvaluationContext *eval_ctx, static void layer_eval_layer_collection_post(ViewLayer *view_layer) { DEG_debug_print_eval(__func__, view_layer->name, view_layer); - /* if base is not selectabled, clear select */ + /* Create array of bases, for fast index-based lookup. */ + const int num_object_bases = BLI_listbase_count(&view_layer->object_bases); + MEM_SAFE_FREE(view_layer->object_bases_array); + view_layer->object_bases_array = MEM_malloc_arrayN( + num_object_bases, sizeof(Base *), "view_layer->object_bases_array"); + int base_index = 0; for (Base *base = view_layer->object_bases.first; base; base = base->next) { + /* if base is not selectabled, clear select. */ if ((base->flag & BASE_SELECTABLED) == 0) { base->flag &= ~BASE_SELECTED; } + /* Store base in the array. */ + view_layer->object_bases_array[base_index++] = base; } } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index de2002624c0..7904e479933 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -433,9 +433,16 @@ void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx), } } -void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx), - Object *object, Base *base, bool is_from_set) +void BKE_object_eval_flush_base_flags(const EvaluationContext *eval_ctx, + Object *object, int base_index, bool is_from_set) { + ViewLayer *view_layer = eval_ctx->view_layer; + BLI_assert(view_layer->object_bases_array != NULL); + BLI_assert(base_index >= 0); + BLI_assert(base_index < MEM_allocN_len(view_layer->object_bases_array) / sizeof(Base *)); + Base *base = view_layer->object_bases_array[base_index]; + BLI_assert(base->object == object); + DEG_debug_print_eval(__func__, object->id.name, object); /* Make sure we have the base collection settings is already populated. diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 7ae8f0410c5..a76350b23c9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6217,6 +6217,7 @@ static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer) view_layer->properties_evaluated = NULL; BLI_listbase_clear(&view_layer->drawdata); + view_layer->object_bases_array = NULL; } /** diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 338d1bc7572..bdc8d7cb572 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -136,6 +136,7 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph) : bmain_(bmain), graph_(graph), scene_(NULL), + view_layer_(NULL), cow_id_hash_(NULL) { } @@ -399,7 +400,7 @@ void DepsgraphNodeBuilder::build_group(Group *group) } /* Build group objects. */ LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) { - build_object(NULL, base->object, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, base->object, DEG_ID_LINKED_INDIRECTLY); } /* Operation to evaluate the whole view layer. * @@ -417,7 +418,7 @@ void DepsgraphNodeBuilder::build_group(Group *group) DEG_OPCODE_VIEW_LAYER_EVAL); } -void DepsgraphNodeBuilder::build_object(Base *base, +void DepsgraphNodeBuilder::build_object(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state) { @@ -429,7 +430,7 @@ void DepsgraphNodeBuilder::build_object(Base *base, * directly. */ if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) { - build_object_flags(base, object, linked_state); + build_object_flags(base_index, object, linked_state); } id_node->linked_state = max(id_node->linked_state, linked_state); return; @@ -439,12 +440,12 @@ void DepsgraphNodeBuilder::build_object(Base *base, id_node->linked_state = linked_state; object->customdata_mask = 0; /* Various flags, flushing from bases/collections. */ - build_object_flags(base, object, linked_state); + build_object_flags(base_index, object, linked_state); /* Transform. */ build_object_transform(object); /* Parent. */ if (object->parent != NULL) { - build_object(NULL, object->parent, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, object->parent, DEG_ID_LINKED_INDIRECTLY); } /* Modifiers. */ if (object->modifiers.first != NULL) { @@ -483,7 +484,7 @@ void DepsgraphNodeBuilder::build_object(Base *base, /* Object that this is a proxy for. */ if (object->proxy) { object->proxy->proxy_from = object; - build_object(NULL, object->proxy, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, object->proxy, DEG_ID_LINKED_INDIRECTLY); } /* Object dupligroup. */ if (object->dup_group != NULL) { @@ -492,11 +493,11 @@ void DepsgraphNodeBuilder::build_object(Base *base, } void DepsgraphNodeBuilder::build_object_flags( - Base *base, + int base_index, Object *object, eDepsNode_LinkedState_Type linked_state) { - if (base == NULL) { + if (base_index == -1) { return; } /* TODO(sergey): Is this really best component to be used? */ @@ -505,7 +506,9 @@ void DepsgraphNodeBuilder::build_object_flags( add_operation_node(&object->id, DEG_NODE_TYPE_LAYER_COLLECTIONS, function_bind(BKE_object_eval_flush_base_flags, - _1, object_cow, base, is_from_set), + _1, + object_cow, base_index, + is_from_set), DEG_OPCODE_OBJECT_BASE_FLAGS); } @@ -877,7 +880,7 @@ void DepsgraphNodeBuilder::build_particles(Object *object) switch (part->ren_as) { case PART_DRAW_OB: if (part->dup_ob != NULL) { - build_object(NULL, + build_object(-1, part->dup_ob, DEG_ID_LINKED_INDIRECTLY); } @@ -1083,13 +1086,13 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object) */ Curve *cu = (Curve *)obdata; if (cu->bevobj != NULL) { - build_object(NULL, cu->bevobj, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, cu->bevobj, DEG_ID_LINKED_INDIRECTLY); } if (cu->taperobj != NULL) { - build_object(NULL, cu->taperobj, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, cu->taperobj, DEG_ID_LINKED_INDIRECTLY); } if (object->type == OB_FONT && cu->textoncurve != NULL) { - build_object(NULL, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY); } break; } @@ -1208,7 +1211,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) build_image((Image *)id); } else if (id_type == ID_OB) { - build_object(NULL, (Object *)id, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY); } else if (id_type == ID_SCE) { /* Scenes are used by compositor trees, and handled by render @@ -1405,7 +1408,7 @@ void DepsgraphNodeBuilder::modifier_walk(void *user_data, } switch (GS(id->name)) { case ID_OB: - data->builder->build_object(NULL, + data->builder->build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY); break; @@ -1430,7 +1433,7 @@ void DepsgraphNodeBuilder::constraint_walk(bConstraint * /*con*/, } switch (GS(id->name)) { case ID_OB: - data->builder->build_object(NULL, + data->builder->build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY); break; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 8c2885614fb..c2aa811c8e6 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -171,10 +171,10 @@ struct DepsgraphNodeBuilder { ViewLayer *view_layer, eDepsNode_LinkedState_Type linked_state); void build_group(Group *group); - void build_object(Base *base, + void build_object(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state); - void build_object_flags(Base *base, + void build_object_flags(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state); void build_object_data(Object *object); @@ -242,6 +242,7 @@ protected: /* State which demotes currently built entities. */ Scene *scene_; + ViewLayer *view_layer_; GHash *cow_id_hash_; BuilderMap built_map_; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index c438efc1644..208462713a5 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -313,7 +313,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object) /* Custom shape. */ if (pchan->custom != NULL) { - build_object(NULL, pchan->custom, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, pchan->custom, DEG_ID_LINKED_INDIRECTLY); } pchan_index++; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index cd9db616bdd..8b770ab81a1 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -76,6 +76,7 @@ void DepsgraphNodeBuilder::build_view_layer( add_time_source(); /* Setup currently building context. */ scene_ = scene; + view_layer_ = view_layer; /* Expand Scene Cow datablock to get proper pointers to bases. */ Scene *scene_cow; ViewLayer *view_layer_cow; @@ -112,17 +113,19 @@ void DepsgraphNodeBuilder::build_view_layer( * but object is expected to be an original one. Hence we go into some * tricks here iterating over the view layer. */ + int base_index = 0; for (Base *base_orig = (Base *)view_layer->object_bases.first, *base_cow = (Base *)view_layer_cow->object_bases.first; base_orig != NULL; base_orig = base_orig->next, base_cow = base_cow->next) { /* object itself */ - build_object(base_cow, base_orig->object, linked_state); + build_object(base_index, base_orig->object, linked_state); base_orig->object->select_color = select_color++; + ++base_index; } if (scene->camera != NULL) { - build_object(NULL, scene->camera, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, scene->camera, DEG_ID_LINKED_INDIRECTLY); } /* Rigidbody. */ if (scene->rigidbody_world != NULL) { diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 806c1ca76fc..2ee0eff7a9c 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -97,6 +97,7 @@ typedef struct ViewLayer { /* Runtime data */ ListBase drawdata; /* ViewLayerEngineData */ + struct Base **object_bases_array; } ViewLayer; typedef struct SceneCollection {