From 6f99dfc0c6032fa5644031f6355ff59e8e10261d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Aug 2020 11:54:18 +0200 Subject: [PATCH] Modifier: Maintain per-modifier session UUID Allows to keep track of modifiers, which is required, for example, for runtime data preservation in depsgraph. --- source/blender/blenkernel/BKE_modifier.h | 6 +++ source/blender/blenkernel/BKE_object.h | 2 + source/blender/blenkernel/intern/modifier.c | 42 +++++++++++++++++++ source/blender/blenkernel/intern/object.c | 6 +++ source/blender/blenloader/intern/readfile.c | 2 + .../intern/eval/deg_eval_copy_on_write.cc | 2 +- source/blender/makesdna/DNA_modifier_types.h | 6 +++ 7 files changed, 65 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index f9590696c2e..98dc411239e 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -413,9 +413,13 @@ void BKE_modifier_type_panel_id(ModifierType type, char *r_idname); * default values if pointer is optional. */ struct ModifierData *BKE_modifier_new(int type); + void BKE_modifier_free_ex(struct ModifierData *md, const int flag); void BKE_modifier_free(struct ModifierData *md); +/* Generate new UUID for the given modifier. */ +void BKE_modifier_session_uuid_generate(struct ModifierData *md); + bool BKE_modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md); void BKE_modifier_copydata_generic(const struct ModifierData *md, @@ -539,6 +543,8 @@ void BKE_modifier_deform_vertsEM(ModifierData *md, struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval, const bool get_cage_mesh); +void BKE_modifier_check_uuids_unique_and_report(const struct Object *object); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 215f4043e34..2029f4d38a1 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -409,6 +409,8 @@ struct Mesh *BKE_object_to_mesh(struct Depsgraph *depsgraph, void BKE_object_to_mesh_clear(struct Object *object); +void BKE_object_check_uuids_unique_and_report(const struct Object *object); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 5789e0f0557..afd02d7001e 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -41,6 +41,7 @@ #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_path_util.h" +#include "BLI_session_uuid.h" #include "BLI_string.h" #include "BLI_string_utils.h" #include "BLI_utildefines.h" @@ -150,6 +151,8 @@ ModifierData *BKE_modifier_new(int type) mti->initData(md); } + BKE_modifier_session_uuid_generate(md); + return md; } @@ -192,6 +195,11 @@ void BKE_modifier_free(ModifierData *md) BKE_modifier_free_ex(md, 0); } +void BKE_modifier_session_uuid_generate(ModifierData *md) +{ + md->session_uuid = BLI_session_uuid_generate(); +} + bool BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md) { if (modifiers && md) { @@ -368,6 +376,17 @@ void BKE_modifier_copydata_ex(ModifierData *md, ModifierData *target, const int mti->foreachObjectLink(target, NULL, (ObjectWalkFunc)modifier_copy_data_id_us_cb, NULL); } } + + if (flag & LIB_ID_CREATE_NO_MAIN) { + /* Make sure UUID is the same between the source and the target. + * This is needed in the cases when UUID is to be preserved and when there is no copyData + * callback, or the copyData does not do full byte copy of the modifier data. */ + target->session_uuid = md->session_uuid; + } + else { + /* In the case copyData made full byte copy force UUID to be re-generated. */ + BKE_modifier_session_uuid_generate(md); + } } void BKE_modifier_copydata(ModifierData *md, ModifierData *target) @@ -1071,3 +1090,26 @@ struct ModifierData *BKE_modifier_get_evaluated(Depsgraph *depsgraph, } return BKE_modifiers_findby_name(object_eval, md->name); } + +void BKE_modifier_check_uuids_unique_and_report(const Object *object) +{ + struct GSet *used_uuids = BLI_gset_new( + BLI_session_uuid_ghash_hash, BLI_session_uuid_ghash_compare, "modifier used uuids"); + + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + const SessionUUID *session_uuid = &md->session_uuid; + if (!BLI_session_uuid_is_generated(session_uuid)) { + printf("Modifier %s -> %s does not have UUID generated.\n", object->id.name + 2, md->name); + continue; + } + + if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) { + printf("Modifier %s -> %s has duplicate UUID generated.\n", object->id.name + 2, md->name); + continue; + } + + BLI_gset_insert(used_uuids, (void *)session_uuid); + } + + BLI_gset_free(used_uuids, NULL); +} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 024e60ea989..31420b3adc6 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -4714,3 +4714,9 @@ void BKE_object_to_mesh_clear(Object *object) BKE_id_free(NULL, object->runtime.object_as_temp_mesh); object->runtime.object_as_temp_mesh = NULL; } + +void BKE_object_check_uuids_unique_and_report(const Object *object) +{ + BKE_pose_check_uuids_unique_and_report(object->pose); + BKE_modifier_check_uuids_unique_and_report(object); +} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e4644ea6e4d..42b97550db1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5296,6 +5296,8 @@ static void direct_link_modifiers(BlendDataReader *reader, ListBase *lb, Object BLO_read_list(reader, lb); for (md = lb->first; md; md = md->next) { + BKE_modifier_session_uuid_generate(md); + md->error = NULL; md->runtime = NULL; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index d76f5991dac..0bf6c38bc89 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -292,7 +292,7 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid) const ID_Type id_type = GS(id_for_copy->name); if (id_type == ID_OB) { const Object *object = reinterpret_cast(id_for_copy); - BKE_pose_check_uuids_unique_and_report(object->pose); + BKE_object_check_uuids_unique_and_report(object); } } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index b01b3f42e6a..fc50261eb03 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -22,6 +22,7 @@ #include "DNA_defs.h" #include "DNA_listBase.h" +#include "DNA_session_uuid_types.h" #ifdef __cplusplus extern "C" { @@ -124,6 +125,11 @@ typedef struct ModifierData { /* Pointer to a ModifierData in the original domain. */ struct ModifierData *orig_modifier_data; + + /* Runtime field which contains unique identifier of the modifier. */ + SessionUUID session_uuid; + + /* Runtime field which contains runtime data which is specific to a modifier type. */ void *runtime; } ModifierData;