diff --git a/source/blender/blenkernel/BKE_duplilist.hh b/source/blender/blenkernel/BKE_duplilist.hh index fd2d9cd666a..0153adbb8c4 100644 --- a/source/blender/blenkernel/BKE_duplilist.hh +++ b/source/blender/blenkernel/BKE_duplilist.hh @@ -8,6 +8,8 @@ * \ingroup bke */ +#include "BLI_vector_list.hh" + #include "BKE_geometry_set.hh" #include "BKE_instances.hh" @@ -23,42 +25,9 @@ struct ViewerPath; /* ---------------------------------------------------- */ /* Dupli-Geometry */ -/** - * \return a #ListBase of #DupliObject. - */ -ListBase *object_duplilist(Depsgraph *depsgraph, - Scene *sce, - Object *ob, - blender::Set *include_objects = nullptr); -/** - * \return a #ListBase of #DupliObject for the preview geometry referenced by the #ViewerPath. - */ -ListBase *object_duplilist_preview(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const ViewerPath *viewer_path); -void free_object_duplilist(ListBase *lb); - -/** - * Get the legacy instances of this object. That includes instances coming from these sources: - * - Particles - * - Dupli Verts - * - Dupli Faces - * - "Objects as Font" - * - * This does not include collection instances which are not considered legacy and should be treated - * properly at a higher level. - * - * Also see #get_dupli_generator for the different existing dupli generators. - */ -blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph, - Scene &scene, - Object &ob); - constexpr int MAX_DUPLI_RECUR = 8; struct DupliObject { - DupliObject *next, *prev; /* Object whose geometry is instanced. */ Object *ob; /* Data owned by the object above that is instanced. This might not be the same as `ob->data`. */ @@ -97,6 +66,41 @@ struct DupliObject { unsigned int random_id; }; +using DupliList = blender::VectorList; + +/** + * Fill a Vector of #DupliObject. + */ +void object_duplilist(Depsgraph *depsgraph, + Scene *sce, + Object *ob, + blender::Set *include_objects, + DupliList &r_duplilist); +/** + * Fill a Vector of #DupliObject for the preview geometry referenced by the #ViewerPath. + */ +void object_duplilist_preview(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + const ViewerPath *viewer_path, + DupliList &r_duplilist); + +/** + * Get the legacy instances of this object. That includes instances coming from these sources: + * - Particles + * - Dupli Verts + * - Dupli Faces + * - "Objects as Font" + * + * This does not include collection instances which are not considered legacy and should be treated + * properly at a higher level. + * + * Also see #get_dupli_generator for the different existing dupli generators. + */ +blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph, + Scene &scene, + Object &ob); + /** * Look up the RGBA value of a uniform shader attribute. * \return true if the attribute was found; if not, r_value is also set to zero. diff --git a/source/blender/blenkernel/BKE_scene.hh b/source/blender/blenkernel/BKE_scene.hh index b48c33eafe2..883231fd7d8 100644 --- a/source/blender/blenkernel/BKE_scene.hh +++ b/source/blender/blenkernel/BKE_scene.hh @@ -9,13 +9,13 @@ #include "BLI_sys_types.h" +#include "BKE_duplilist.hh" + struct Base; struct Collection; struct Depsgraph; -struct DupliObject; struct GHash; struct Main; -struct ListBase; struct Object; struct RenderData; struct Scene; @@ -73,8 +73,9 @@ Object *BKE_scene_object_find_by_name(const Scene *scene, const char *name); * Define struct here, so no need to bother with alloc/free it. */ struct SceneBaseIter { - ListBase *duplilist; + DupliList duplilist; DupliObject *dupob; + int dupob_index; float omat[4][4]; Object *dupli_refob; int phase; diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 90b44f7855b..d585cdc3d59 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -3809,28 +3809,28 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph, return ok; } - ListBase *lb = object_duplilist(depsgraph, scene, ob); - LISTBASE_FOREACH (DupliObject *, dob, lb) { - if (((use_hidden == false) && (dob->no_draw != 0)) || dob->ob_data == nullptr) { + DupliList duplilist; + object_duplilist(depsgraph, scene, ob, nullptr, duplilist); + for (DupliObject &dob : duplilist) { + if (((use_hidden == false) && (dob.no_draw != 0)) || dob.ob_data == nullptr) { /* pass */ } else { - Object temp_ob = blender::dna::shallow_copy(*dob->ob); - blender::bke::ObjectRuntime runtime = *dob->ob->runtime; + Object temp_ob = blender::dna::shallow_copy(*dob.ob); + blender::bke::ObjectRuntime runtime = *dob.ob->runtime; temp_ob.runtime = &runtime; /* Do not modify the original bounding-box. */ temp_ob.runtime->bounds_eval.reset(); - BKE_object_replace_data_on_shallow_copy(&temp_ob, dob->ob_data); + BKE_object_replace_data_on_shallow_copy(&temp_ob, dob.ob_data); if (const std::optional> bounds = BKE_object_boundbox_get(&temp_ob)) { BoundBox bb; BKE_boundbox_init_from_minmax(&bb, bounds->min, bounds->max); - BKE_boundbox_minmax(bb, float4x4(dob->mat), r_min, r_max); + BKE_boundbox_minmax(bb, float4x4(dob.mat), r_min, r_max); ok = true; } } } - free_object_duplilist(lb); /* does restore */ return ok; } diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 0dfc776049d..f6ebf4ced5f 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -28,7 +28,7 @@ #include "BLI_set.hh" #include "BLI_span.hh" #include "BLI_string_ref.hh" -#include "BLI_vector.hh" +#include "BLI_vector_list.hh" #include "DNA_collection_types.h" #include "DNA_curves_types.h" @@ -75,6 +75,7 @@ using blender::float4x4; using blender::Set; using blender::Span; using blender::Vector; +using blender::VectorList; using blender::bke::GeometrySet; using blender::bke::InstanceReference; using blender::bke::Instances; @@ -137,7 +138,7 @@ struct DupliContext { const struct DupliGenerator *gen; /** Result containers. */ - ListBase *duplilist; /* Legacy doubly-linked list. */ + DupliList *duplilist; }; struct DupliGenerator { @@ -158,7 +159,8 @@ static void init_context(DupliContext *r_ctx, const float space_mat[4][4], blender::Set *include_objects, Vector &instance_stack, - Vector &dupli_gen_type_stack) + Vector &dupli_gen_type_stack, + DupliList &duplilist) { r_ctx->depsgraph = depsgraph; r_ctx->scene = scene; @@ -169,6 +171,7 @@ static void init_context(DupliContext *r_ctx, r_ctx->obedit = OBEDIT_FROM_OBACT(ob); r_ctx->instance_stack = &instance_stack; r_ctx->dupli_gen_type_stack = &dupli_gen_type_stack; + r_ctx->duplilist = &duplilist; if (space_mat) { copy_m4_m4(r_ctx->space_mat, space_mat); } @@ -182,7 +185,6 @@ static void init_context(DupliContext *r_ctx, r_ctx->dupli_gen_type_stack->append(r_ctx->gen->type); } - r_ctx->duplilist = nullptr; r_ctx->preview_instance_index = -1; r_ctx->preview_base_geometry = nullptr; @@ -268,8 +270,8 @@ static DupliObject *make_dupli(const DupliContext *ctx, /* Add a #DupliObject instance to the result container. */ if (ctx->duplilist) { - dob = MEM_callocN("dupli object"); - BLI_addtail(ctx->duplilist, dob); + ctx->duplilist->append({}); + dob = &ctx->duplilist->last(); } else { return nullptr; @@ -1804,39 +1806,49 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) /** \name Dupli-Container Implementation * \{ */ -ListBase *object_duplilist(Depsgraph *depsgraph, - Scene *sce, - Object *ob, - Set *include_objects) +void object_duplilist(Depsgraph *depsgraph, + Scene *sce, + Object *ob, + Set *include_objects, + DupliList &r_duplilist) { - ListBase *duplilist = MEM_callocN("duplilist"); DupliContext ctx; Vector instance_stack; Vector dupli_gen_type_stack({0}); instance_stack.append(ob); - init_context( - &ctx, depsgraph, sce, ob, nullptr, include_objects, instance_stack, dupli_gen_type_stack); + init_context(&ctx, + depsgraph, + sce, + ob, + nullptr, + include_objects, + instance_stack, + dupli_gen_type_stack, + r_duplilist); if (ctx.gen) { - ctx.duplilist = duplilist; ctx.gen->make_duplis(&ctx); } - - return duplilist; } -ListBase *object_duplilist_preview(Depsgraph *depsgraph, - Scene *sce, - Object *ob_eval, - const ViewerPath *viewer_path) +void object_duplilist_preview(Depsgraph *depsgraph, + Scene *sce, + Object *ob_eval, + const ViewerPath *viewer_path, + DupliList &r_duplilist) { - ListBase *duplilist = MEM_callocN("duplilist"); DupliContext ctx; Vector instance_stack; Vector dupli_gen_type_stack({0}); instance_stack.append(ob_eval); - init_context( - &ctx, depsgraph, sce, ob_eval, nullptr, nullptr, instance_stack, dupli_gen_type_stack); - ctx.duplilist = duplilist; + init_context(&ctx, + depsgraph, + sce, + ob_eval, + nullptr, + nullptr, + instance_stack, + dupli_gen_type_stack, + r_duplilist); Object *ob_orig = DEG_get_original(ob_eval); @@ -1859,7 +1871,6 @@ ListBase *object_duplilist_preview(Depsgraph *depsgraph, ob_eval->type == OB_CURVES); } } - return duplilist; } blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph, @@ -1868,19 +1879,25 @@ blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph, { using namespace blender; - ListBase *duplilist = MEM_callocN("duplilist"); DupliContext ctx; + DupliList duplilist; Vector instance_stack({&ob}); Vector dupli_gen_type_stack({0}); - init_context( - &ctx, &depsgraph, &scene, &ob, nullptr, nullptr, instance_stack, dupli_gen_type_stack); + init_context(&ctx, + &depsgraph, + &scene, + &ob, + nullptr, + nullptr, + instance_stack, + dupli_gen_type_stack, + duplilist); if (ctx.gen == &gen_dupli_geometry_set) { /* These are not legacy instances. */ return {}; } if (ctx.gen) { - ctx.duplilist = duplilist; ctx.gen->make_duplis(&ctx); } const bool is_particle_duplis = ctx.gen == &gen_dupli_particles; @@ -1889,12 +1906,12 @@ blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph, const int level_to_use = is_particle_duplis ? 1 : 0; Vector top_level_duplis; - LISTBASE_FOREACH (DupliObject *, dob, duplilist) { - BLI_assert(dob->ob != &ob); + for (DupliObject &dob : duplilist) { + BLI_assert(dob.ob != &ob); /* We only need the top level instances in the end, because when #Instances references an * object, it implicitly also references all instances of that object. */ - if (dob->level == level_to_use) { - top_level_duplis.append(dob); + if (dob.level == level_to_use) { + top_level_duplis.append(&dob); } } @@ -1933,16 +1950,9 @@ blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph, } instances_ids.finish(); - free_object_duplilist(duplilist); return top_level_instances; } -void free_object_duplilist(ListBase *lb) -{ - BLI_freelistN(lb); - MEM_freeN(lb); -} - /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc index 5f91353a589..e78e3b87914 100644 --- a/source/blender/blenkernel/intern/scene.cc +++ b/source/blender/blenkernel/intern/scene.cc @@ -2095,7 +2095,8 @@ int BKE_scene_base_iter_next( if (val == 0) { iter->phase = F_START; iter->dupob = nullptr; - iter->duplilist = nullptr; + iter->dupob_index = -1; + iter->duplilist.clear(); iter->dupli_refob = nullptr; } else { @@ -2164,13 +2165,14 @@ int BKE_scene_base_iter_next( * this enters eternal loop because of * makeDispListMBall getting called inside of collection_duplilist */ if ((*base)->object->instance_collection == nullptr) { - iter->duplilist = object_duplilist(depsgraph, (*scene), (*base)->object); + object_duplilist(depsgraph, (*scene), (*base)->object, nullptr, iter->duplilist); - iter->dupob = static_cast(iter->duplilist->first); + iter->dupob = iter->duplilist.is_empty() ? nullptr : &iter->duplilist.first(); + iter->dupob_index = 0; if (!iter->dupob) { - free_object_duplilist(iter->duplilist); - iter->duplilist = nullptr; + iter->duplilist.clear(); + iter->dupob_index = -1; } iter->dupli_refob = nullptr; } @@ -2193,7 +2195,13 @@ int BKE_scene_base_iter_next( } copy_m4_m4((*ob)->runtime->object_to_world.ptr(), iter->dupob->mat); - iter->dupob = iter->dupob->next; + if (++iter->dupob_index < iter->duplilist.size()) { + iter->dupob = &iter->duplilist[iter->dupob_index]; + } + else { + iter->dupob = nullptr; + iter->dupob_index = -1; + } } else if (iter->phase == F_DUPLI) { iter->phase = F_SCENE; @@ -2205,8 +2213,7 @@ int BKE_scene_base_iter_next( iter->dupli_refob = nullptr; } - free_object_duplilist(iter->duplilist); - iter->duplilist = nullptr; + iter->duplilist.clear(); run_again = true; } } diff --git a/source/blender/depsgraph/DEG_depsgraph_query.hh b/source/blender/depsgraph/DEG_depsgraph_query.hh index cbcfd95d783..724a81c3c41 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.hh +++ b/source/blender/depsgraph/DEG_depsgraph_query.hh @@ -21,6 +21,7 @@ /* Needed for the instance iterator. */ #include "DNA_object_types.h" +#include "BKE_duplilist.hh" #include "BKE_object_types.hh" struct BLI_Iterator; @@ -265,9 +266,11 @@ struct DEGObjectIterData { /* Object which created the dupli-list. */ Object *dupli_parent; /* List of duplicated objects. */ - ListBase *dupli_list; + DupliList dupli_list; /* Next duplicated object to step into. */ DupliObject *dupli_object_next; + /* The dupli_list index of dupli_object_next. */ + int dupli_object_next_index; /* Corresponds to current object: current iterator object is evaluated from * this duplicated object. */ DupliObject *dupli_object_current; @@ -279,7 +282,9 @@ struct DEGObjectIterData { /* **** Iteration over ID nodes **** */ size_t id_node_index; size_t num_id_nodes; - DEGObjectIterData &operator=(const DEGObjectIterData &other); + + /* Copy the current/next data and move the DupliList. */ + void transfer_from(DEGObjectIterData &other); }; void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data); diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 567af4d1262..9efc9fff04d 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -113,17 +113,17 @@ bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject return false; } -void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object, ListBase *duplis) +void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object) { data->dupli_parent = object; - data->dupli_list = duplis; - data->dupli_object_next = static_cast(duplis->first); + data->dupli_object_next = data->dupli_list.is_empty() ? nullptr : &data->dupli_list.first(); + data->dupli_object_next_index = data->dupli_object_next ? 0 : -1; } /* Returns false when iterator is exhausted. */ bool deg_iterator_duplis_step(DEGObjectIterData *data) { - if (data->dupli_list == nullptr) { + if (data->dupli_list.is_empty()) { return false; } @@ -131,7 +131,13 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) DupliObject *dob = data->dupli_object_next; Object *obd = dob->ob; - data->dupli_object_next = data->dupli_object_next->next; + if (++data->dupli_object_next_index < data->dupli_list.size()) { + data->dupli_object_next = &data->dupli_list[data->dupli_object_next_index]; + } + else { + data->dupli_object_next = nullptr; + data->dupli_object_next_index = -1; + } if (dob->no_draw) { continue; @@ -196,10 +202,10 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) } free_owned_memory(data); - free_object_duplilist(data->dupli_list); + data->dupli_list.clear(); data->dupli_parent = nullptr; - data->dupli_list = nullptr; data->dupli_object_next = nullptr; + data->dupli_object_next_index = -1; data->dupli_object_current = nullptr; deg_invalidate_iterator_work_data(data); return false; @@ -265,9 +271,9 @@ bool deg_iterator_objects_step(DEGObjectIterData *data) const bool use_preview = object_orig == data->object_orig_with_preview; if (use_preview) { - ListBase *preview_duplis = object_duplilist_preview( - data->graph, data->scene, object, data->settings->viewer_path); - deg_iterator_duplis_init(data, object, preview_duplis); + object_duplilist_preview( + data->graph, data->scene, object, data->settings->viewer_path, data->dupli_list); + deg_iterator_duplis_init(data, object); data->id_node_index++; return true; } @@ -286,9 +292,9 @@ bool deg_iterator_objects_step(DEGObjectIterData *data) ((object->transflag & OB_DUPLI) || object->runtime->geometry_set_eval != nullptr)) { BLI_assert(deg::deg_validate_eval_copy_datablock(&object->id)); - ListBase *duplis = object_duplilist( - data->graph, data->scene, object, data->settings->included_objects); - deg_iterator_duplis_init(data, object, duplis); + object_duplilist( + data->graph, data->scene, object, data->settings->included_objects, data->dupli_list); + deg_iterator_duplis_init(data, object); } } @@ -304,27 +310,27 @@ bool deg_iterator_objects_step(DEGObjectIterData *data) } // namespace -DEGObjectIterData &DEGObjectIterData::operator=(const DEGObjectIterData &other) +void DEGObjectIterData::transfer_from(DEGObjectIterData &other) { - if (this != &other) { - this->settings = other.settings; - this->graph = other.graph; - this->flag = other.flag; - this->scene = other.scene; - this->eval_mode = other.eval_mode; - this->object_orig_with_preview = other.object_orig_with_preview; - this->next_object = other.next_object; - this->dupli_parent = other.dupli_parent; - this->dupli_list = other.dupli_list; - this->dupli_object_next = other.dupli_object_next; - this->dupli_object_current = other.dupli_object_current; - this->temp_dupli_object = blender::dna::shallow_copy(other.temp_dupli_object); - this->temp_dupli_object_runtime = other.temp_dupli_object_runtime; - this->temp_dupli_object.runtime = &temp_dupli_object_runtime; - this->id_node_index = other.id_node_index; - this->num_id_nodes = other.num_id_nodes; - } - return *this; + BLI_assert(this != &other); + + this->settings = other.settings; + this->graph = other.graph; + this->flag = other.flag; + this->scene = other.scene; + this->eval_mode = other.eval_mode; + this->object_orig_with_preview = other.object_orig_with_preview; + this->next_object = other.next_object; + this->dupli_parent = other.dupli_parent; + this->dupli_list = std::move(other.dupli_list); + this->dupli_object_next = other.dupli_object_next; + this->dupli_object_next_index = other.dupli_object_next_index; + this->dupli_object_current = other.dupli_object_current; + this->temp_dupli_object = blender::dna::shallow_copy(other.temp_dupli_object); + this->temp_dupli_object_runtime = other.temp_dupli_object_runtime; + this->temp_dupli_object.runtime = &temp_dupli_object_runtime; + this->id_node_index = other.id_node_index; + this->num_id_nodes = other.num_id_nodes; } static Object *find_object_with_preview_geometry(const ViewerPath &viewer_path) @@ -374,8 +380,9 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) data->next_object = nullptr; data->dupli_parent = nullptr; - data->dupli_list = nullptr; + data->dupli_list.clear(); data->dupli_object_next = nullptr; + data->dupli_object_next_index = -1; data->dupli_object_current = nullptr; data->scene = DEG_get_evaluated_scene(depsgraph); data->id_node_index = 0; diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_bake_animation.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_bake_animation.cc index 04b0d24238c..f3629da7a09 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_bake_animation.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_bake_animation.cc @@ -77,19 +77,21 @@ static Vector get_bake_targets(bContext &C, Depsgraph &depsgraph, Scen Vector bake_targets; Object *active_object = CTX_data_active_object(&C); + DupliList duplilist; + if (active_object->type == OB_GREASE_PENCIL) { bake_targets.append(active_object); } else if (active_object->type == OB_EMPTY) { - ListBase *lb = object_duplilist(&depsgraph, &scene, active_object); - LISTBASE_FOREACH (DupliObject *, duplicate_object, lb) { - if (duplicate_object->ob->type != OB_GREASE_PENCIL) { + object_duplilist(&depsgraph, &scene, active_object, nullptr, duplilist); + for (DupliObject &duplicate_object : duplilist) { + if (duplicate_object.ob->type != OB_GREASE_PENCIL) { continue; } - bake_targets.append(duplicate_object->ob); + bake_targets.append(duplicate_object.ob); } - free_object_duplilist(lb); + duplilist.clear(); } CTX_DATA_BEGIN (&C, Object *, object, selected_objects) { @@ -101,15 +103,15 @@ static Vector get_bake_targets(bContext &C, Depsgraph &depsgraph, Scen bake_targets.append(object); } else if (object->type == OB_EMPTY) { - ListBase *lb = object_duplilist(&depsgraph, &scene, active_object); - LISTBASE_FOREACH (DupliObject *, duplicate_object, lb) { - if (duplicate_object->ob->type != OB_GREASE_PENCIL) { + object_duplilist(&depsgraph, &scene, active_object, nullptr, duplilist); + for (DupliObject &duplicate_object : duplilist) { + if (duplicate_object.ob->type != OB_GREASE_PENCIL) { continue; } - bake_targets.append(duplicate_object->ob); + bake_targets.append(duplicate_object.ob); } - free_object_duplilist(lb); + duplilist.clear(); } } CTX_DATA_END; diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index 13132729653..a6f7e78938d 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -2498,10 +2498,10 @@ static void make_object_duplilist_real(bContext *C, return; } - ListBase *lb_duplis = object_duplilist(depsgraph, scene, object_eval); + DupliList duplilist; + object_duplilist(depsgraph, scene, object_eval, nullptr, duplilist); - if (BLI_listbase_is_empty(lb_duplis)) { - free_object_duplilist(lb_duplis); + if (duplilist.is_empty()) { return; } @@ -2515,8 +2515,8 @@ static void make_object_duplilist_real(bContext *C, } } - LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) { - Object *ob_src = DEG_get_original(dob->ob); + for (DupliObject &dob : duplilist) { + Object *ob_src = DEG_get_original(dob.ob); Object *ob_dst = static_cast(ID_NEW_SET(ob_src, BKE_id_copy(bmain, &ob_src->id))); id_us_min(&ob_dst->id); @@ -2551,32 +2551,32 @@ static void make_object_duplilist_real(bContext *C, id_us_min((ID *)ob_dst->instance_collection); ob_dst->instance_collection = nullptr; - copy_m4_m4(ob_dst->runtime->object_to_world.ptr(), dob->mat); + copy_m4_m4(ob_dst->runtime->object_to_world.ptr(), dob.mat); BKE_object_apply_mat4(ob_dst, ob_dst->object_to_world().ptr(), false, false); - dupli_map.add(dob, ob_dst); + dupli_map.add(&dob, ob_dst); if (parent_gh) { void **val; /* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as * 'the same', this avoids trying to insert same key several time and * raise asserts in debug builds... */ - if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) { + if (!BLI_ghash_ensure_p(parent_gh, &dob, &val)) { *val = ob_dst; } if (is_dupli_instancer && instancer_gh) { /* Same as above, we may have several 'hits'. */ - if (!BLI_ghash_ensure_p(instancer_gh, dob, &val)) { + if (!BLI_ghash_ensure_p(instancer_gh, &dob, &val)) { *val = ob_dst; } } } } - LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) { - Object *ob_src = dob->ob; - Object *ob_dst = dupli_map.lookup(dob); + for (DupliObject &dob : duplilist) { + Object *ob_src = dob.ob; + Object *ob_dst = dupli_map.lookup(&dob); /* Remap new object to itself, and clear again newid pointer of orig object. */ BKE_libblock_relink_to_newid(bmain, &ob_dst->id, 0); @@ -2594,14 +2594,14 @@ static void make_object_duplilist_real(bContext *C, * they won't be read, this is simply for a hash lookup. */ DupliObject dob_key; dob_key.ob = ob_src_par; - dob_key.type = dob->type; - if (dob->type == OB_DUPLICOLLECTION) { + dob_key.type = dob.type; + if (dob.type == OB_DUPLICOLLECTION) { memcpy(&dob_key.persistent_id[1], - &dob->persistent_id[1], - sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1)); + &dob.persistent_id[1], + sizeof(dob.persistent_id[1]) * (MAX_DUPLI_RECUR - 1)); } else { - dob_key.persistent_id[0] = dob->persistent_id[0]; + dob_key.persistent_id[0] = dob.persistent_id[0]; } ob_dst_par = static_cast(BLI_ghash_lookup(parent_gh, &dob_key)); } @@ -2630,7 +2630,7 @@ static void make_object_duplilist_real(bContext *C, * ignoring the first item. * We only check on persistent_id here, since we have no idea what object it might be. */ memcpy(&dob_key.persistent_id[0], - &dob->persistent_id[1], + &dob.persistent_id[1], sizeof(dob_key.persistent_id[0]) * (MAX_DUPLI_RECUR - 1)); ob_dst_par = static_cast(BLI_ghash_lookup(instancer_gh, &dob_key)); } @@ -2648,7 +2648,7 @@ static void make_object_duplilist_real(bContext *C, if (ob_dst->parent) { /* NOTE: this may be the parent of other objects, but it should * still work out ok */ - BKE_object_apply_mat4(ob_dst, dob->mat, false, true); + BKE_object_apply_mat4(ob_dst, dob.mat, false, true); /* to set ob_dst->orig and in case there's any other discrepancies */ DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM); @@ -2669,8 +2669,6 @@ static void make_object_duplilist_real(bContext *C, BLI_ghash_free(instancer_gh, nullptr, nullptr); } - free_object_duplilist(lb_duplis); - BKE_main_id_newptr_and_tag_clear(bmain); base->object->transflag &= ~OB_DUPLI; diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 84896709cc6..a6c9fa60eee 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -472,6 +472,7 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, IterSnapObjsCallback BKE_view_layer_synced_ensure(scene, view_layer); Base *base_act = BKE_view_layer_active_base_get(view_layer); + DupliList duplilist; LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (!snap_object_is_snappable(sctx, snap_target_select, base_act, base)) { continue; @@ -482,20 +483,20 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, IterSnapObjsCallback if (obj_eval->transflag & OB_DUPLI || blender::bke::object_has_geometry_set_instances(*obj_eval)) { - ListBase *lb = object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval); - LISTBASE_FOREACH (DupliObject *, dupli_ob, lb) { - BLI_assert(DEG_is_evaluated(dupli_ob->ob)); + object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval, nullptr, duplilist); + for (DupliObject &dupli_ob : duplilist) { + BLI_assert(DEG_is_evaluated(dupli_ob.ob)); if ((tmp = sob_callback(sctx, - dupli_ob->ob, - dupli_ob->ob_data, - float4x4(dupli_ob->mat), + dupli_ob.ob, + dupli_ob.ob_data, + float4x4(dupli_ob.mat), is_object_active, false)) != SCE_SNAP_TO_NONE) { ret = tmp; } } - free_object_duplilist(lb); + duplilist.clear(); } bool use_hide = false; diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 1832548d9f7..0d116363a5c 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -14,9 +14,6 @@ #include "BlenderStrokeRenderer.h" -using namespace std; -using namespace Freestyle; - #include "MEM_guardedalloc.h" #include "DNA_collection_types.h" @@ -50,6 +47,9 @@ using namespace Freestyle; #include "FRS_freestyle.h" +using namespace std; +using namespace Freestyle; + FreestyleGlobals g_freestyle; // Freestyle configuration diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc index ac0ecc2ef88..dcdef1d69c8 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc @@ -287,6 +287,7 @@ void AbstractHierarchyIterator::export_graph_construct() deg_iter_settings.depsgraph = depsgraph_; deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET; + DupliList duplilist; DEG_OBJECT_ITER_BEGIN (°_iter_settings, object) { /* Non-instanced objects always have their object-parent as export-parent. */ const bool weak_export = mark_as_weak_export(object); @@ -298,27 +299,27 @@ void AbstractHierarchyIterator::export_graph_construct() } /* Export the duplicated objects instanced by this object. */ - ListBase *lb = object_duplilist(depsgraph_, scene, object); - if (lb) { + object_duplilist(depsgraph_, scene, object, nullptr, duplilist); + if (!duplilist.is_empty()) { DupliParentFinder dupli_parent_finder; - LISTBASE_FOREACH (DupliObject *, dupli_object, lb) { - PersistentID persistent_id(dupli_object); - if (!should_visit_dupli_object(dupli_object)) { + for (DupliObject &dupli_object : duplilist) { + PersistentID persistent_id(&dupli_object); + if (!should_visit_dupli_object(&dupli_object)) { continue; } - dupli_parent_finder.insert(dupli_object); + dupli_parent_finder.insert(&dupli_object); } - LISTBASE_FOREACH (DupliObject *, dupli_object, lb) { - if (!should_visit_dupli_object(dupli_object)) { + for (DupliObject &dupli_object : duplilist) { + if (!should_visit_dupli_object(&dupli_object)) { continue; } - visit_dupli_object(dupli_object, object, dupli_parent_finder); + visit_dupli_object(&dupli_object, object, dupli_parent_finder); } } - free_object_duplilist(lb); + duplilist.clear(); } DEG_OBJECT_ITER_END; } diff --git a/source/blender/makesrna/intern/rna_depsgraph.cc b/source/blender/makesrna/intern/rna_depsgraph.cc index 6c2e1a7bd5e..29b8f8e0e93 100644 --- a/source/blender/makesrna/intern/rna_depsgraph.cc +++ b/source/blender/makesrna/intern/rna_depsgraph.cc @@ -400,7 +400,7 @@ static void rna_Depsgraph_object_instances_next(CollectionPropertyIterator *iter /* We need to copy current iterator status to next one being worked on. */ di_it->iterators[(di_it->counter + 1) % 2].iter = di_it->iterators[di_it->counter % 2].iter; - di_it->deg_data[(di_it->counter + 1) % 2] = di_it->deg_data[di_it->counter % 2]; + di_it->deg_data[(di_it->counter + 1) % 2].transfer_from(di_it->deg_data[di_it->counter % 2]); di_it->counter++; di_it->iterators[di_it->counter % 2].iter.data = &di_it->deg_data[di_it->counter % 2];