Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h8
-rw-r--r--source/blender/blenkernel/BKE_main_idmap.h20
-rw-r--r--source/blender/blenkernel/intern/lib_id.c31
-rw-r--r--source/blender/blenkernel/intern/main_idmap.c68
-rw-r--r--source/blender/blenloader/intern/readfile.c13
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/makesdna/DNA_ID.h10
-rw-r--r--source/blender/windowmanager/intern/wm_files.c7
8 files changed, 136 insertions, 23 deletions
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index cb86d54009b..27dd1e637f3 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -67,6 +67,14 @@ void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const
ATTR_WARN_UNUSED_RESULT;
void BKE_libblock_init_empty(struct ID *id) ATTR_NONNULL(1);
+/* *** ID's session_uuid management. *** */
+
+/* When an ID's uuid is of that value, it is unset/invalid (e.g. for runtime IDs, etc.). */
+#define MAIN_ID_SESSION_UUID_UNSET 0
+
+void BKE_lib_libblock_session_uuid_reset(void);
+void BKE_lib_libblock_session_uuid_ensure(struct ID *id);
+
void *BKE_id_new(struct Main *bmain, const short type, const char *name);
void *BKE_id_new_nomain(const short type, const char *name);
diff --git a/source/blender/blenkernel/BKE_main_idmap.h b/source/blender/blenkernel/BKE_main_idmap.h
index a68d27a7882..e392b7db60e 100644
--- a/source/blender/blenkernel/BKE_main_idmap.h
+++ b/source/blender/blenkernel/BKE_main_idmap.h
@@ -40,22 +40,32 @@ struct ID;
struct IDNameLib_Map;
struct Main;
+enum {
+ MAIN_IDMAP_TYPE_NAME = 1 << 0,
+ MAIN_IDMAP_TYPE_UUID = 1 << 1,
+};
+
struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
const bool create_valid_ids_set,
- struct Main *old_bmain) ATTR_WARN_UNUSED_RESULT
+ struct Main *old_bmain,
+ const int idmap_types) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1);
void BKE_main_idmap_destroy(struct IDNameLib_Map *id_typemap) ATTR_NONNULL();
struct Main *BKE_main_idmap_main_get(struct IDNameLib_Map *id_typemap) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
-struct ID *BKE_main_idmap_lookup(struct IDNameLib_Map *id_typemap,
- short id_type,
- const char *name,
- const struct Library *lib) ATTR_WARN_UNUSED_RESULT
+struct ID *BKE_main_idmap_lookup_name(struct IDNameLib_Map *id_typemap,
+ short id_type,
+ const char *name,
+ const struct Library *lib) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 3);
struct ID *BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_typemap,
const struct ID *id) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 2);
+struct ID *BKE_main_idmap_lookup_uuid(struct IDNameLib_Map *id_typemap,
+ const uint session_uuid) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 416de844691..92e9a7c6c79 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1027,6 +1027,8 @@ void BKE_libblock_management_main_add(Main *bmain, void *idv)
id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT);
bmain->is_memfile_undo_written = false;
BKE_main_unlock(bmain);
+
+ BKE_lib_libblock_session_uuid_ensure(id);
}
/** Remove a data-block from given main (set it to 'NO_MAIN' status). */
@@ -1313,6 +1315,8 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
/* alphabetic insertion: is in new_id */
BKE_main_unlock(bmain);
+ BKE_lib_libblock_session_uuid_ensure(id);
+
/* TODO to be removed from here! */
if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
DEG_id_type_tag(bmain, type);
@@ -1456,6 +1460,33 @@ void BKE_libblock_init_empty(ID *id)
}
}
+/* ********** ID session-wise UUID management. ********** */
+static uint global_session_uuid = 0;
+
+/** Reset the session-wise uuid counter (used when reading a new file e.g.). */
+void BKE_lib_libblock_session_uuid_reset()
+{
+ global_session_uuid = 0;
+}
+
+/**
+ * Generate a session-wise uuid for the given \a id.
+ *
+ * \note "session-wise" here means while editing a given .blend file. Once a new .blend file is
+ * loaded or created, undo history is cleared/reset, and so is the uuid counter.
+ */
+void BKE_lib_libblock_session_uuid_ensure(ID *id)
+{
+ if (id->session_uuid == MAIN_ID_SESSION_UUID_UNSET) {
+ id->session_uuid = atomic_add_and_fetch_uint32(&global_session_uuid, 1);
+ /* In case overflow happens, still assign a valid ID. This way opening files many times works
+ * correctly. */
+ if (UNLIKELY(id->session_uuid == MAIN_ID_SESSION_UUID_UNSET)) {
+ id->session_uuid = atomic_add_and_fetch_uint32(&global_session_uuid, 1);
+ }
+ }
+}
+
/**
* Generic helper to create a new empty data-block of given type in given \a bmain database.
*
diff --git a/source/blender/blenkernel/intern/main_idmap.c b/source/blender/blenkernel/intern/main_idmap.c
index a210961b212..26eb0b681a1 100644
--- a/source/blender/blenkernel/intern/main_idmap.c
+++ b/source/blender/blenkernel/intern/main_idmap.c
@@ -26,6 +26,7 @@
#include "DNA_ID.h"
#include "BKE_idcode.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_main_idmap.h" /* own include */
@@ -65,16 +66,20 @@ struct IDNameLib_TypeMap {
*/
struct IDNameLib_Map {
struct IDNameLib_TypeMap type_maps[MAX_LIBARRAY];
+ struct GHash *uuid_map;
struct Main *bmain;
struct GSet *valid_id_pointers;
+ int idmap_types;
};
static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id_map,
short id_type)
{
- for (int i = 0; i < MAX_LIBARRAY; i++) {
- if (id_map->type_maps[i].id_type == id_type) {
- return &id_map->type_maps[i];
+ if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) {
+ for (int i = 0; i < MAX_LIBARRAY; i++) {
+ if (id_map->type_maps[i].id_type == id_type) {
+ return &id_map->type_maps[i];
+ }
}
}
return NULL;
@@ -94,9 +99,12 @@ static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id
*/
struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
const bool create_valid_ids_set,
- struct Main *old_bmain)
+ struct Main *old_bmain,
+ const int idmap_types)
{
struct IDNameLib_Map *id_map = MEM_mallocN(sizeof(*id_map), __func__);
+ id_map->bmain = bmain;
+ id_map->idmap_types = idmap_types;
int index = 0;
while (index < MAX_LIBARRAY) {
@@ -107,7 +115,22 @@ struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
}
BLI_assert(index == MAX_LIBARRAY);
- id_map->bmain = bmain;
+ if (idmap_types & MAIN_IDMAP_TYPE_UUID) {
+ ID *id;
+ id_map->uuid_map = BLI_ghash_int_new(__func__);
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ BLI_assert(id->session_uuid != MAIN_ID_SESSION_UUID_UNSET);
+ void **id_ptr_v;
+ const bool existing_key = BLI_ghash_ensure_p(
+ id_map->uuid_map, POINTER_FROM_UINT(id->session_uuid), &id_ptr_v);
+ BLI_assert(existing_key == false);
+ *id_ptr_v = id;
+ }
+ FOREACH_MAIN_ID_END;
+ }
+ else {
+ id_map->uuid_map = NULL;
+ }
if (create_valid_ids_set) {
id_map->valid_id_pointers = BKE_main_gset_create(bmain, NULL);
@@ -144,10 +167,10 @@ static bool idkey_cmp(const void *a, const void *b)
return strcmp(idkey_a->name, idkey_b->name) || (idkey_a->lib != idkey_b->lib);
}
-ID *BKE_main_idmap_lookup(struct IDNameLib_Map *id_map,
- short id_type,
- const char *name,
- const Library *lib)
+ID *BKE_main_idmap_lookup_name(struct IDNameLib_Map *id_map,
+ short id_type,
+ const char *name,
+ const Library *lib)
{
struct IDNameLib_TypeMap *type_map = main_idmap_from_idcode(id_map, id_type);
@@ -188,21 +211,34 @@ ID *BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_map, const ID *id)
* when trying to get ID name).
*/
if (id_map->valid_id_pointers == NULL || BLI_gset_haskey(id_map->valid_id_pointers, id)) {
- return BKE_main_idmap_lookup(id_map, GS(id->name), id->name + 2, id->lib);
+ return BKE_main_idmap_lookup_name(id_map, GS(id->name), id->name + 2, id->lib);
+ }
+ return NULL;
+}
+
+ID *BKE_main_idmap_lookup_uuid(struct IDNameLib_Map *id_map, const uint session_uuid)
+{
+ if (id_map->idmap_types & MAIN_IDMAP_TYPE_UUID) {
+ return BLI_ghash_lookup(id_map->uuid_map, POINTER_FROM_UINT(session_uuid));
}
return NULL;
}
void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map)
{
- struct IDNameLib_TypeMap *type_map = id_map->type_maps;
- for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) {
- if (type_map->map) {
- BLI_ghash_free(type_map->map, NULL, NULL);
- type_map->map = NULL;
- MEM_freeN(type_map->keys);
+ if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) {
+ struct IDNameLib_TypeMap *type_map = id_map->type_maps;
+ for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) {
+ if (type_map->map) {
+ BLI_ghash_free(type_map->map, NULL, NULL);
+ type_map->map = NULL;
+ MEM_freeN(type_map->keys);
+ }
}
}
+ if (id_map->idmap_types & MAIN_IDMAP_TYPE_UUID) {
+ BLI_ghash_free(id_map->uuid_map, NULL, NULL);
+ }
if (id_map->valid_id_pointers != NULL) {
BLI_gset_free(id_map->valid_id_pointers, NULL);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 3107de38ff7..4d46435eea0 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8056,7 +8056,8 @@ void blo_lib_link_restore(Main *oldmain,
Scene *curscene,
ViewLayer *cur_view_layer)
{
- struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain, true, oldmain);
+ struct IDNameLib_Map *id_map = BKE_main_idmap_create(
+ newmain, true, oldmain, MAIN_IDMAP_TYPE_NAME);
for (WorkSpace *workspace = newmain->workspaces.first; workspace;
workspace = workspace->id.next) {
@@ -8801,6 +8802,8 @@ static ID *create_placeholder(Main *mainvar, const short idcode, const char *idn
BLI_addtail(lb, ph_id);
id_sort_by_name(lb, ph_id, NULL);
+ BKE_lib_libblock_session_uuid_ensure(ph_id);
+
return ph_id;
}
@@ -9013,6 +9016,14 @@ static BHead *read_libblock(FileData *fd,
oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
BLI_addtail(lb, id);
+
+ if (fd->memfile == NULL) {
+ /* When actually reading a file , we do want to reset/re-generate session uuids.
+ * In unod case, we want to re-use existing ones. */
+ id->session_uuid = MAIN_ID_SESSION_UUID_UNSET;
+ }
+
+ BKE_lib_libblock_session_uuid_ensure(id);
}
else {
/* unknown ID type */
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index a4b51f91be4..cf4924eeb6d 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -446,6 +446,8 @@ static void versions_gpencil_add_main(ListBase *lb, ID *id, const char *name)
BKE_id_new_name_validate(lb, id, name);
/* alphabetic insertion: is in BKE_id_new_name_validate */
+ BKE_lib_libblock_session_uuid_ensure(id);
+
if (G.debug & G_DEBUG) {
printf("Converted GPencil to ID: %s\n", id->name + 2);
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 89af705d5ed..3ac93a96661 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -31,6 +31,8 @@
extern "C" {
#endif
+#include "DNA_defs.h"
+
struct FileData;
struct GHash;
struct GPUTexture;
@@ -243,7 +245,13 @@ typedef struct ID {
int us;
int icon_id;
int recalc;
- char _pad[4];
+
+ /**
+ * A session-wide unique identifier for a given ID, that remain the same across potential
+ * re-allocations (e.g. due to undo/redo steps).
+ */
+ unsigned int session_uuid;
+
IDProperty *properties;
/** Reference linked ID which this one overrides. */
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index dae6f62319d..2dcacc3dc30 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -77,6 +77,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
+#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
@@ -611,6 +612,9 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
UI_view2d_zoom_cache_reset();
+ /* Reset session-wise ID UUID counter. */
+ BKE_lib_libblock_session_uuid_reset();
+
/* first try to append data from exotic file formats... */
/* it throws error box when file doesn't exist and returns -1 */
/* note; it should set some error message somewhere... (ton) */
@@ -917,6 +921,9 @@ void wm_homefile_read(bContext *C,
}
}
+ /* Reset session-wise ID UUID counter. */
+ BKE_lib_libblock_session_uuid_reset();
+
if (!use_factory_settings || (filepath_startup[0] != '\0')) {
if (BLI_access(filepath_startup, R_OK) == 0) {
success = BKE_blendfile_read(C,