From 3f6ef965b91d91b8a22015b5831c43f28f8e036e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 1 Oct 2025 15:03:41 +0200 Subject: [PATCH] Refactor: LightLinking: Add creation/copy/delete API for Object data. Similar to what we do with modifiers, constraints, and so on. Avoids spreading knowledge about internal data handling in several parts of the code. Pull Request: https://projects.blender.org/blender/blender/pulls/147122 --- source/blender/blenkernel/BKE_light_linking.h | 23 ++++++++++++ .../blenkernel/intern/light_linking.cc | 37 +++++++++++++++++-- source/blender/blenkernel/intern/object.cc | 7 ++-- .../intern/depsgraph_light_linking.cc | 2 +- .../eval/deg_eval_runtime_backup_object.cc | 5 +-- 5 files changed, 63 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_light_linking.h b/source/blender/blenkernel/BKE_light_linking.h index 0d895c31345..817b0189414 100644 --- a/source/blender/blenkernel/BKE_light_linking.h +++ b/source/blender/blenkernel/BKE_light_linking.h @@ -25,6 +25,29 @@ typedef enum LightLinkingType { LIGHT_LINKING_BLOCKER, } LightLinkingType; +/** + * Add an empty LightLinking data to an Object. + */ +void BKE_light_linking_ensure(struct Object *object); + +/** + * Copy the LightLinking data from `object_src` to `object_dst`. + * + * \param copy_flags Flags controlling the copy process, see e.g. #LIB_ID_CREATE_NO_USER_REFCOUNT + * and related flags in the same enum. + */ +void BKE_light_linking_copy(struct Object *object_dst, + const struct Object *object_src, + const int copy_flags); + +/** + * Free the LightLinking data from the object. + * + * \param copy_flags Flags controlling the copy process, see e.g. #LIB_ID_CREATE_NO_USER_REFCOUNT + * and related flags in the same enum. + */ +void BKE_light_linking_delete(struct Object *object, const int delete_flags); + /** * Free object's light_linking if it is not needed to hold any of collections. */ diff --git a/source/blender/blenkernel/intern/light_linking.cc b/source/blender/blenkernel/intern/light_linking.cc index 53f80e6f41a..9094c4df354 100644 --- a/source/blender/blenkernel/intern/light_linking.cc +++ b/source/blender/blenkernel/intern/light_linking.cc @@ -27,12 +27,43 @@ #include "DEG_depsgraph.hh" #include "DEG_depsgraph_build.hh" +void BKE_light_linking_ensure(struct Object *object) +{ + if (object->light_linking == nullptr) { + object->light_linking = MEM_callocN(__func__); + } +} + +void BKE_light_linking_copy(Object *object_dst, const Object *object_src, const int copy_flags) +{ + BLI_assert(ELEM(object_dst->light_linking, nullptr, object_src->light_linking)); + if (object_src->light_linking) { + object_dst->light_linking = MEM_dupallocN(__func__, + *(object_src->light_linking)); + if ((copy_flags & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus(blender::id_cast(object_dst->light_linking->receiver_collection)); + id_us_plus(blender::id_cast(object_dst->light_linking->blocker_collection)); + } + } +} + +void BKE_light_linking_delete(struct Object *object, const int delete_flags) +{ + if (object->light_linking) { + if ((delete_flags & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_min(blender::id_cast(object->light_linking->receiver_collection)); + id_us_min(blender::id_cast(object->light_linking->blocker_collection)); + } + MEM_SAFE_FREE(object->light_linking); + } +} + void BKE_light_linking_free_if_empty(Object *object) { if (object->light_linking->receiver_collection == nullptr && object->light_linking->blocker_collection == nullptr) { - MEM_SAFE_FREE(object->light_linking); + BKE_light_linking_delete(object, LIB_ID_CREATE_NO_USER_REFCOUNT); } } @@ -97,8 +128,8 @@ void BKE_light_linking_collection_assign_only(Object *object, } /* Allocate light linking on demand. */ - if (new_collection && !object->light_linking) { - object->light_linking = MEM_callocN(__func__); + if (new_collection) { + BKE_light_linking_ensure(object); } if (object->light_linking) { diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index db5fc19f956..73fba5900c4 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -101,6 +101,7 @@ #include "BKE_lib_remap.hh" #include "BKE_library.hh" #include "BKE_light.h" +#include "BKE_light_linking.h" #include "BKE_lightprobe.h" #include "BKE_linestyle.h" #include "BKE_main.hh" @@ -266,9 +267,7 @@ static void object_copy_data(Main *bmain, if (ob_src->lightgroup) { ob_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(ob_src->lightgroup); } - if (ob_src->light_linking) { - ob_dst->light_linking = (LightLinking *)MEM_dupallocN(ob_src->light_linking); - } + BKE_light_linking_copy(ob_dst, ob_src, flag_subdata); if ((flag & LIB_ID_COPY_SET_COPIED_ON_WRITE) != 0) { if (ob_src->lightprobe_cache) { @@ -332,7 +331,7 @@ static void object_free_data(ID *id) BKE_previewimg_free(&ob->preview); MEM_SAFE_FREE(ob->lightgroup); - MEM_SAFE_FREE(ob->light_linking); + BKE_light_linking_delete(ob, LIB_ID_CREATE_NO_USER_REFCOUNT); BKE_lightprobe_cache_free(ob); diff --git a/source/blender/depsgraph/intern/depsgraph_light_linking.cc b/source/blender/depsgraph/intern/depsgraph_light_linking.cc index 65f92c77786..1f618c62014 100644 --- a/source/blender/depsgraph/intern/depsgraph_light_linking.cc +++ b/source/blender/depsgraph/intern/depsgraph_light_linking.cc @@ -481,7 +481,7 @@ void Cache::eval_runtime_data(Object &object_eval) const } } else if (need_runtime) { - object_eval.light_linking = MEM_callocN(__func__); + BKE_light_linking_ensure(&object_eval); object_eval.light_linking->runtime = runtime; } } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc index 6784e3be6f9..6f2110ece2c 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -17,6 +17,7 @@ #include "BLI_listbase.h" #include "BKE_action.hh" +#include "BKE_light_linking.h" #include "BKE_mesh_types.hh" #include "BKE_modifier.hh" #include "BKE_object.hh" @@ -131,9 +132,7 @@ void ObjectRuntimeBackup::restore_to_object(Object *object) if (light_linking_runtime) { /* Lazily allocate light linking on the evaluated object for the cases when the object is only * a receiver or a blocker and does not need its own LightLinking on the original object. */ - if (!object->light_linking) { - object->light_linking = MEM_callocN(__func__); - } + BKE_light_linking_ensure(object); object->light_linking->runtime = *light_linking_runtime; }