[Bf-blender-cvs] [901791944da] master: Anim: Refactor 'F-curve from rna path' code.

Bastien Montagne noreply at git.blender.org
Thu Jun 2 12:36:52 CEST 2022


Commit: 901791944da9cb66b68841ff8615758cec407b5a
Author: Bastien Montagne
Date:   Tue May 31 17:28:52 2022 +0200
Branches: master
https://developer.blender.org/rB901791944da9cb66b68841ff8615758cec407b5a

Anim: Refactor 'F-curve from rna path' code.

Move into its own new function the the low-level logic to search for a
given RNA path in Action F-curves, then driver F-curves of a given AnimData.

This deduplicates code from `BKE_fcurve_find_by_rna_context_ui` and
`id_data_find_fcurve`, and will allow for future more usages of this
functionality.

Differential Revision: https://developer.blender.org/D15068

===================================================================

M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/fcurve.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 78d80ce200e..30c73e0fcc6 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -259,6 +259,18 @@ struct FCurve *BKE_fcurve_iter_step(struct FCurve *fcu_iter, const char rna_path
 
 /**
  * High level function to get an f-curve from C without having the RNA.
+ *
+ * If there is an action assigned to the `id`'s #AnimData, it will be searched for a matching
+ * F-curve first. Drivers are searched only if no valid action F-curve could be found.
+ *
+ * \note: Return pointer parameter (`r_driven`) is optional and may be NULL.
+ *
+ * \warning: In case no animation (from an Action) F-curve is found, returned value is always NULL.
+ * This means that this function will set `r_driven` to True in case a valid driver F-curve is
+ * found, but will not return said F-curve. In other words:
+ *   - Animated with FCurve: returns the `FCurve*` and `*r_driven = false`.
+ *   - Animated with driver: returns `NULL` and `*r_driven = true`.
+ *   - Not animated: returns `NULL` and `*r_driven = false`.
  */
 struct FCurve *id_data_find_fcurve(
     ID *id, void *data, struct StructRNA *type, const char *prop_name, int index, bool *r_driven);
@@ -278,6 +290,25 @@ struct FCurve *id_data_find_fcurve(
  */
 int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName);
 
+/**
+ * Find an F-Curve from its rna path and index.
+ *
+ * If there is an action assigned to the `animdata`, it will be searched for a matching F-curve
+ * first. Drivers are searched only if no valid action F-curve could be found.
+ *
+ * \note: Typically, indices in RNA arrays are stored separately in F-curves, so the rna_path
+ * should not include them (e.g. `rna_path='location[0]'` will not match any F-Curve on an Object,
+ * but `rna_path='location', rna_index=0` will if it exists).
+ *
+ * \note: Return pointer parameters (`r_action`, `r_driven` and `r_special`) are all optional and
+ * may be NULL.
+ */
+struct FCurve *BKE_animadata_fcurve_find_by_rna_path(struct AnimData *animdata,
+                                                     const char *rna_path,
+                                                     const int rna_index,
+                                                     struct bAction **r_action,
+                                                     bool *r_driven);
+
 /**
  * Find an f-curve based on an rna property.
  */
@@ -291,7 +322,9 @@ struct FCurve *BKE_fcurve_find_by_rna(struct PointerRNA *ptr,
 /**
  * Same as above, but takes a context data,
  * temp hack needed for complex paths like texture ones.
- */
+ *
+ * \param r_special Optional, ignored when NULL. Set to `true` if the given RNA `ptr` is a NLA
+ * strip, and the returned F-curve comes from this NLA strip. */
 struct FCurve *BKE_fcurve_find_by_rna_context_ui(struct bContext *C,
                                                  const struct PointerRNA *ptr,
                                                  struct PropertyRNA *prop,
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 952d5df299c..98a2b977d4e 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -229,16 +229,13 @@ FCurve *id_data_find_fcurve(
     return NULL;
   }
 
-  /* Animation takes priority over drivers. */
-  if (adt->action && adt->action->curves.first) {
-    fcu = BKE_fcurve_find(&adt->action->curves, path, index);
-  }
-
-  /* If not animated, check if driven. */
-  if (fcu == NULL && adt->drivers.first) {
-    fcu = BKE_fcurve_find(&adt->drivers, path, index);
-    if (fcu && r_driven) {
-      *r_driven = true;
+  /* FIXME: The way drivers are handled here (always NULL-ifying `fcu`) is very weird, this needs
+   * to be re-checked I think?. */
+  bool is_driven = false;
+  fcu = BKE_animadata_fcurve_find_by_rna_path(adt, path, index, NULL, &is_driven);
+  if (is_driven) {
+    if (r_driven != NULL) {
+      *r_driven = is_driven;
     }
     fcu = NULL;
   }
@@ -339,6 +336,47 @@ int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, con
   return matches;
 }
 
+FCurve *BKE_animadata_fcurve_find_by_rna_path(
+    AnimData *animdata, const char *rna_path, int rna_index, bAction **r_action, bool *r_driven)
+{
+  if (r_driven != NULL) {
+    *r_driven = false;
+  }
+  if (r_action != NULL) {
+    *r_action = NULL;
+  }
+
+  const bool has_action_fcurves = animdata->action != NULL &&
+                                  !BLI_listbase_is_empty(&animdata->action->curves);
+  const bool has_drivers = !BLI_listbase_is_empty(&animdata->drivers);
+
+  /* Animation takes priority over drivers. */
+  if (has_action_fcurves) {
+    FCurve *fcu = BKE_fcurve_find(&animdata->action->curves, rna_path, rna_index);
+
+    if (fcu != NULL) {
+      if (r_action != NULL) {
+        *r_action = animdata->action;
+      }
+      return fcu;
+    }
+  }
+
+  /* If not animated, check if driven. */
+  if (has_drivers) {
+    FCurve *fcu = BKE_fcurve_find(&animdata->drivers, rna_path, rna_index);
+
+    if (fcu != NULL) {
+      if (r_driven != NULL) {
+        *r_driven = true;
+      }
+      return fcu;
+    }
+  }
+
+  return NULL;
+}
+
 FCurve *BKE_fcurve_find_by_rna(PointerRNA *ptr,
                                PropertyRNA *prop,
                                int rnaindex,
@@ -360,17 +398,18 @@ FCurve *BKE_fcurve_find_by_rna_context_ui(bContext *UNUSED(C),
                                           bool *r_driven,
                                           bool *r_special)
 {
-  FCurve *fcu = NULL;
-
-  *r_driven = false;
-  *r_special = false;
-
-  if (r_animdata) {
+  if (r_animdata != NULL) {
     *r_animdata = NULL;
   }
-  if (r_action) {
+  if (r_action != NULL) {
     *r_action = NULL;
   }
+  if (r_driven != NULL) {
+    *r_driven = false;
+  }
+  if (r_special) {
+    *r_special = false;
+  }
 
   /* Special case for NLA Control Curves... */
   if (BKE_nlastrip_has_curves_for_property(ptr, prop)) {
@@ -379,59 +418,46 @@ FCurve *BKE_fcurve_find_by_rna_context_ui(bContext *UNUSED(C),
     /* Set the special flag, since it cannot be a normal action/driver
      * if we've been told to start looking here...
      */
-    *r_special = true;
+    if (r_special) {
+      *r_special = true;
+    }
+
+    *r_driven = false;
+    if (r_animdata) {
+      *r_animdata = NULL;
+    }
+    if (r_action) {
+      *r_action = NULL;
+    }
 
     /* The F-Curve either exists or it doesn't here... */
-    fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), rnaindex);
-    return fcu;
+    return BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), rnaindex);
   }
 
   /* There must be some RNA-pointer + property combo. */
   if (!prop || !ptr->owner_id || !RNA_property_animateable(ptr, prop)) {
-    return fcu;
+    return NULL;
   }
 
   AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
   if (adt == NULL) {
-    return fcu;
+    return NULL;
   }
 
-  const bool has_action_fcurves = adt->action != NULL &&
-                                  !BLI_listbase_is_empty(&adt->action->curves);
-  const bool has_drivers = !BLI_listbase_is_empty(&adt->drivers);
-
   /* XXX This function call can become a performance bottleneck. */
-  char *path = RNA_path_from_ID_to_property(ptr, prop);
-
-  /* Standard F-Curve - Animation (Action) or Drivers. */
-  /* Animation takes priority over drivers. */
-  /* XXX: The logic here is duplicated with a function up above. */
-  if (has_action_fcurves) {
-    fcu = BKE_fcurve_find(&adt->action->curves, path, rnaindex);
-
-    if (fcu) {
-      if (r_action) {
-        *r_action = adt->action;
-      }
-      if (r_animdata) {
-        *r_animdata = adt;
-      }
-    }
+  char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+  if (rna_path == NULL) {
+    return NULL;
   }
 
-  /* If not animated, check if driven. */
-  if (fcu == NULL && has_drivers) {
-    fcu = BKE_fcurve_find(&adt->drivers, path, rnaindex);
+  /* Standard F-Curve from animdata - Animation (Action) or Drivers. */
+  FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(adt, rna_path, rnaindex, r_action, r_driven);
 
-    if (fcu) {
-      if (r_animdata) {
-        *r_animdata = adt;
-      }
-      *r_driven = true;
-    }
+  if (fcu != NULL && r_animdata != NULL) {
+    *r_animdata = adt;
   }
 
-  MEM_SAFE_FREE(path);
+  MEM_freeN(rna_path);
   return fcu;
 }



More information about the Bf-blender-cvs mailing list