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:
authorJoshua Leung <aligorith@gmail.com>2011-07-24 08:34:46 +0400
committerJoshua Leung <aligorith@gmail.com>2011-07-24 08:34:46 +0400
commit6a392e8cb505b753a0bac24e42778306007c45b8 (patch)
tree6d34591894fec168b8535fae88455ef8446f0a2a /source/blender/makesrna/intern/rna_access.c
parentc22f26d2032b7116477e6a378407a10b6d7e3276 (diff)
== RNA Property Updates get called by Animation System now ==
This fixes bug #26764 and several others like it, where modifier properties (and others, but most visibly modifiers) would not do anything when animated or driven, as modifier properties require the RNA update calls to tag the modifiers to get recalculated. While just adding a call to RNA_property_update() could have gotten this working (as per the Campbell's patch attached in the report, and also my own attempt #25881). However, on production rigs, the performance cost of this is untenatable (on my own tests, without these updates, I was getting ~5fps on such a rig, but only 0.9fps or possibly even worse with the updates added). Hence, this commit adds a property-update caching system to the RNA level, which aims to reduce to the number of times that the update functions end up needing to get called. While this is much faster than without the caching, I also added an optimisation for pose bones (which are numerous in production rigs) so that their property updates are skipped, since they are useless to the animsys (they only tag the depsgraph for updating). This gets things moving at a more acceptable framerate.
Diffstat (limited to 'source/blender/makesrna/intern/rna_access.c')
-rw-r--r--source/blender/makesrna/intern/rna_access.c110
1 files changed, 109 insertions, 1 deletions
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 285e8ca39ba..7936fc4c280 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -85,7 +85,9 @@ void RNA_init(void)
void RNA_exit(void)
{
StructRNA *srna;
-
+
+ RNA_property_update_cache_free();
+
for(srna=BLENDER_RNA.structs.first; srna; srna=srna->cont.next) {
if(srna->cont.prophash) {
BLI_ghash_free(srna->cont.prophash, NULL, NULL);
@@ -1391,6 +1393,112 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper
rna_property_update(NULL, bmain, scene, ptr, prop);
}
+
+/* RNA Updates Cache ------------------------ */
+/* Overview of RNA Update cache system:
+ *
+ * RNA Update calls need to be cached in order to maintain reasonable performance
+ * of the animation system (i.e. maintaining a somewhat interactive framerate)
+ * while still allowing updates to be called (necessary in particular for modifier
+ * property updates to actually work).
+ *
+ * The cache is structured with a dual-layer structure
+ * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
+ * and most updates end up using just that anyways)
+ * - L2 = Update functions to be called on those PointerRNA's
+ */
+
+/* cache element */
+typedef struct tRnaUpdateCacheElem {
+ struct tRnaUpdateCacheElem *next, *prev;
+
+ PointerRNA ptr; /* L1 key - id as primary, data secondary/ignored? */
+ ListBase L2Funcs; /* L2 functions (LinkData<RnaUpdateFuncRef>) */
+} tRnaUpdateCacheElem;
+
+/* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
+static ListBase rna_updates_cache = {NULL, NULL};
+
+/* ........................... */
+
+void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
+{
+ tRnaUpdateCacheElem *uce = NULL;
+ UpdateFunc fn = NULL;
+ LinkData *ld;
+ short is_rna = (prop->magic == RNA_MAGIC);
+
+ /* sanity check */
+ if (ELEM(NULL, ptr, prop))
+ return;
+
+ prop= rna_ensure_property(prop);
+
+ /* we can only handle update calls with no context args for now (makes animsys updates easier) */
+ if ((is_rna == 0) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
+ return;
+ fn = prop->update;
+
+ /* find cache element for which key matches... */
+ for (uce = rna_updates_cache.first; uce; uce = uce->next) {
+ /* just match by id only for now, since most update calls that we'll encounter only really care about this */
+ // TODO: later, the cache might need to have some nesting on L1 to cope better with these problems + some tagging to indicate we need this
+ if (uce->ptr.id.data == ptr->id.data)
+ break;
+ }
+ if (uce == NULL) {
+ /* create new instance */
+ uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
+ BLI_addtail(&rna_updates_cache, uce);
+
+ /* copy pointer */
+ RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
+ }
+
+ /* check on the update func */
+ for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
+ /* stop on match - function already cached */
+ if (fn == ld->data)
+ return;
+ }
+ /* else... if still here, we need to add it */
+ BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
+}
+
+void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
+{
+ tRnaUpdateCacheElem *uce;
+
+ // TODO: should we check that bmain and scene are valid? The above stuff doesn't!
+
+ /* execute the cached updates */
+ for (uce = rna_updates_cache.first; uce; uce = uce->next) {
+ LinkData *ld;
+
+ for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
+ UpdateFunc fn = (UpdateFunc)ld->data;
+ fn(bmain, scene, &uce->ptr);
+ }
+ }
+}
+
+void RNA_property_update_cache_free(void)
+{
+ tRnaUpdateCacheElem *uce, *ucn;
+
+ for (uce = rna_updates_cache.first; uce; uce = ucn) {
+ ucn = uce->next;
+
+ /* free L2 cache */
+ BLI_freelistN(&uce->L2Funcs);
+
+ /* remove self */
+ BLI_freelinkN(&rna_updates_cache, uce);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
/* Property Data */
int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)