Page MenuHome
Paste P1275

Generic API to to check if an object has been updated
ActivePublic

Authored by Campbell Barton (campbellbarton) on Feb 27 2020, 8:02 AM.
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 9f436db97ee..d5d066e426c 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -39,6 +39,7 @@ struct Mesh;
struct ModifierData;
struct MovieClip;
struct Object;
+struct Object_UpdateTag;
struct RegionView3D;
struct RigidBodyWorld;
struct Scene;
@@ -359,6 +360,10 @@ struct MovieClip *BKE_object_movieclip_get(struct Scene *scene,
void BKE_object_runtime_reset(struct Object *object);
void BKE_object_runtime_reset_on_copy(struct Object *object, const int flag);
+void BKE_object_runtime_update_tag_add(struct Object *ob, struct Object_UpdateTag *update_tag);
+void BKE_object_runtime_update_tag_remove(struct Object *ob, struct Object_UpdateTag *update_tag);
+void BKE_object_runtime_update_tag_set(struct Object *ob, int flag);
+
void BKE_object_batch_cache_dirty_tag(struct Object *ob);
/* this function returns a superset of the scenes selection based on relationships */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 51d397a44bc..61c82196830 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -454,6 +454,10 @@ void BKE_object_free_derived_caches(Object *ob)
/* clear grease pencil data */
DRW_gpencil_freecache(ob);
+
+ if (ob->runtime.update_links != NULL) {
+ BKE_object_runtime_update_tag_set(ob, OBJECT_UPDATE_FLAG_GEOM);
+ }
}
void BKE_object_free_caches(Object *object)
@@ -3931,6 +3935,45 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
runtime->gpencil_cache = NULL;
}
+void BKE_object_runtime_update_tag_add(struct Object *ob, Object_UpdateTag *update_tag)
+{
+#ifndef NDEBUG
+ {
+ Object_UpdateTag *tag_step = ob->runtime.update_links;
+ while (tag_step != NULL) {
+ BLI_assert(tag_step != update_tag);
+ tag_step = tag_step->next;
+ }
+ }
+#endif
+ update_tag->next = ob->runtime.update_links;
+ ob->runtime.update_links = update_tag;
+}
+
+void BKE_object_runtime_update_tag_remove(struct Object *ob, Object_UpdateTag *update_tag)
+{
+ Object_UpdateTag *tag_step = ob->runtime.update_links;
+ Object_UpdateTag **tag_link = &ob->runtime.update_links;
+ while (tag_step != NULL) {
+ if (tag_step == update_tag) {
+ *tag_link = update_tag->next;
+ break;
+ }
+ tag_link = &tag_step->next;
+ tag_step = tag_step->next;
+ }
+ /* Assert if not found. */
+ BLI_assert(tag_step != NULL);
+}
+
+void BKE_object_runtime_update_tag_set(struct Object *ob, int flag)
+{
+ Object_UpdateTag *tag_step = ob->runtime.update_links;
+ while (tag_step) {
+ tag_step->flag |= flag;
+ }
+}
+
/*
* Find an associated Armature object
*/
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index eb926c51ba9..e2f8ed82c8f 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -48,6 +48,7 @@ typedef unsigned int (*GHashHashFP)(const void *key);
typedef bool (*GHashCmpFP)(const void *a, const void *b);
typedef void (*GHashKeyFreeFP)(void *key);
typedef void (*GHashValFreeFP)(void *val);
+typedef void (*GHashKeyValFreeFP)(void *key, void *val);
typedef void *(*GHashKeyCopyFP)(const void *key);
typedef void *(*GHashValCopyFP)(const void *val);
@@ -90,6 +91,7 @@ GHash *BLI_ghash_copy(GHash *gh,
GHashKeyCopyFP keycopyfp,
GHashValCopyFP valcopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+void BLI_ghash_free_pair(GHash *gh, GHashKeyValFreeFP keyval_freefp);
void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve);
void BLI_ghash_insert(GHash *gh, void *key, void *val);
bool BLI_ghash_reinsert(
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 1c518cf1487..c91d73879f0 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -655,6 +655,24 @@ static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP va
}
}
+static void ghash_free_pair_cb(GHash *gh, GHashKeyValFreeFP keyval_freefp)
+{
+ uint i;
+
+ BLI_assert(keyval_freefp);
+ BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
+ if (keyval_freefp == NULL) {
+ return;
+ }
+
+ for (i = 0; i < gh->nbuckets; i++) {
+ Entry *e;
+ for (e = gh->buckets[i]; e; e = e->next) {
+ keyval_freefp(e->key, ((GHashEntry *)e)->val);
+ }
+ }
+}
+
/**
* Copy the GHash.
*/
@@ -1030,6 +1048,18 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreef
MEM_freeN(gh);
}
+void BLI_ghash_free_pair(GHash *gh, GHashKeyValFreeFP keyval_freefp)
+{
+ BLI_assert((int)gh->nentries == BLI_mempool_len(gh->entrypool));
+ if (keyval_freefp) {
+ ghash_free_pair_cb(gh, keyval_freefp);
+ }
+
+ MEM_freeN(gh->buckets);
+ BLI_mempool_destroy(gh->entrypool);
+ MEM_freeN(gh);
+}
+
/**
* Sets a GHash flag.
*/
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index c4358168adb..7b90e53bd92 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -92,6 +92,7 @@ typedef struct SnapObjectData {
SNAP_MESH = 1,
SNAP_EDIT_MESH,
} type;
+ Object_UpdateTag update_link;
} SnapObjectData;
typedef struct SnapObjectData_Mesh {
@@ -190,6 +191,7 @@ static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, O
else {
SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
sod->sd.type = SNAP_MESH;
+ BKE_object_runtime_update_tag_add(ob, &sod->sd.update_link);
/* start assuming that it has each of these element types */
sod->has_looptris = true;
sod->has_loose_edge = true;
@@ -227,6 +229,7 @@ static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext
SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena,
sizeof(*sod));
sod->sd.type = SNAP_EDIT_MESH;
+ BKE_object_runtime_update_tag_add(ob, &sod->sd.update_link);
bm_mesh_minmax(em->bm, sod->min, sod->max);
}
@@ -523,7 +526,8 @@ static bool raycastMesh(SnapObjectContext *sctx,
/* The tree is owned by the Mesh and may have been freed since we last used. */
if (treedata->tree) {
BLI_assert(treedata->cached);
- if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
+ if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree) ||
+ (sod->sd.update_link.flag & OBJECT_UPDATE_FLAG_GEOM)) {
free_bvhtree_from_mesh(treedata);
}
else {
@@ -544,6 +548,8 @@ static bool raycastMesh(SnapObjectContext *sctx,
}
if (treedata->tree == NULL) {
+ sod->sd.update_link.flag &= ~OBJECT_UPDATE_FLAG_GEOM;
+
if (use_hide) {
BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI_NO_HIDDEN, 4);
}
@@ -700,12 +706,15 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
/* The tree is owned by the Mesh and may have been freed since we last used! */
- if (treedata->tree && !bvhcache_has_tree(*em_bvh_cache, treedata->tree)) {
+ if ((treedata->tree && !bvhcache_has_tree(*em_bvh_cache, treedata->tree)) &&
+ (sod->sd.update_link.flag & OBJECT_UPDATE_FLAG_GEOM)) {
free_bvhtree_from_editmesh(treedata);
}
}
if (treedata->tree == NULL) {
+ sod->sd.update_link.flag &= ~OBJECT_UPDATE_FLAG_GEOM;
+
/* Get original version of the edit_mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
@@ -2792,8 +2801,10 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
return sctx;
}
-static void snap_object_data_free(void *sod_v)
+static void snap_object_data_free(void *ob_v, void *sod_v)
{
+ BKE_object_runtime_update_tag_remove((Object *)ob_v, &((SnapObjectData *)sod_v)->update_link);
+
switch (((SnapObjectData *)sod_v)->type) {
case SNAP_MESH: {
SnapObjectData_Mesh *sod = sod_v;
@@ -2816,7 +2827,7 @@ static void snap_object_data_free(void *sod_v)
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
{
- BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
+ BLI_ghash_free_pair(sctx->cache.object_map, snap_object_data_free);
if (sctx->cache.data_to_object_map != NULL) {
BLI_ghash_free(sctx->cache.data_to_object_map, NULL, NULL);
}
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index b142939eaeb..3da77e9da3f 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -118,6 +118,17 @@ typedef struct LodLevel {
int obhysteresis;
} LodLevel;
+#
+#
+typedef struct Object_UpdateTag {
+ struct Object_UpdateTag *next;
+ int flag;
+} Object_UpdateTag;
+
+enum {
+ OBJECT_UPDATE_FLAG_GEOM = (1 << 0),
+};
+
struct CustomData_MeshMasks;
/* Not saved in file! */
@@ -182,6 +193,7 @@ typedef struct Object_Runtime {
char _pad4[4];
/** Runtime grease pencil evaluated data created by modifiers */
struct bGPDframe *gpencil_evaluated_frames;
+ struct Object_UpdateTag *update_links;
unsigned short local_collections_bits;
short _pad2[3];