[Bf-blender-cvs] [83c8f996f16] master: UI: Add callback for comparing button identity

Julian Eisel noreply at git.blender.org
Tue Apr 26 22:31:23 CEST 2022


Commit: 83c8f996f1618a51496100dc680a877a89be7a4e
Author: Julian Eisel
Date:   Tue Apr 26 22:26:15 2022 +0200
Branches: master
https://developer.blender.org/rB83c8f996f1618a51496100dc680a877a89be7a4e

UI: Add callback for comparing button identity

The code to compare buttons from the previous to the current frame, to
see if they match (an thus should keep the same state) was quite
generic, and didn't allow much flexibility/customization. For some
cases this isn't enough, and a more specific comparison is needed. Say
if some buttons don't actually store comparable data themselves, only
via the button context. This was the case in D14653.

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.cc
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_utils.cc

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 94453ef5fac..1b817d06564 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -508,6 +508,10 @@ typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2);
 typedef void (*uiButHandleHoldFunc)(struct bContext *C, struct ARegion *butregion, uiBut *but);
 typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
 
+/** Function to compare the identity of two buttons over redraws, to check if they represent the
+ * same data, and thus should be considered the same button over redraws. */
+typedef bool (*uiButIdentityCompareFunc)(const uiBut *a, const uiBut *b);
+
 /* Search types. */
 typedef struct ARegion *(*uiButSearchCreateFn)(struct bContext *C,
                                                struct ARegion *butregion,
@@ -1649,6 +1653,18 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
                                      eButLabelAlign label_align,
                                      bool compact);
 
+/**
+ * Callback to compare the identity of two buttons, used to identify buttons over redraws. If the
+ * callback returns true, the given buttons are considered to be matching and relevant state is
+ * preserved (copied from the old to the new button). If it returns false, it's considered
+ * non-matching and no further checks are done.
+ *
+ * If this is set, it is always executed instead of the default comparisons. However it is only
+ * executed for buttons that have the same type and the same callback. So callbacks can assume the
+ * button types match.
+ */
+void UI_but_func_identity_compare_set(uiBut *but, uiButIdentityCompareFunc cmp_fn);
+
 /**
  * Public function exported for functions that use #UI_BTYPE_SEARCH_MENU.
  *
diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc
index 9310ede31fa..b7098c26bcd 100644
--- a/source/blender/editors/interface/interface.cc
+++ b/source/blender/editors/interface/interface.cc
@@ -725,6 +725,19 @@ bool ui_but_rna_equals_ex(const uiBut *but,
 /* NOTE: if `but->poin` is allocated memory for every `uiDefBut*`, things fail. */
 static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
 {
+  if (but->identity_cmp_func) {
+    /* If the buttons have own identity comparator callbacks (and they match), use this to
+     * determine equality. */
+    if (but->identity_cmp_func && (but->type == oldbut->type) &&
+        (but->identity_cmp_func == oldbut->identity_cmp_func)) {
+      /* Test if the comparison is symmetrical (if a == b then b == a), may help catch some issues.
+       */
+      BLI_assert(but->identity_cmp_func(but, oldbut) == but->identity_cmp_func(oldbut, but));
+
+      return but->identity_cmp_func(but, oldbut);
+    }
+  }
+
   /* various properties are being compared here, hopefully sufficient
    * to catch all cases, but it is simple to add more checks later */
   if (but->retval != oldbut->retval) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 05acdac3597..c09ff68bbca 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -183,6 +183,9 @@ struct uiBut {
 
   uchar col[4];
 
+  /** See \ref UI_but_func_identity_compare_set(). */
+  uiButIdentityCompareFunc identity_cmp_func;
+
   uiButHandleFunc func;
   void *func_arg1;
   void *func_arg2;
diff --git a/source/blender/editors/interface/interface_utils.cc b/source/blender/editors/interface/interface_utils.cc
index c59863f462a..993ccdf92f7 100644
--- a/source/blender/editors/interface/interface_utils.cc
+++ b/source/blender/editors/interface/interface_utils.cc
@@ -452,6 +452,11 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
   return return_info;
 }
 
+void UI_but_func_identity_compare_set(uiBut *but, uiButIdentityCompareFunc cmp_fn)
+{
+  but->identity_cmp_func = cmp_fn;
+}
+
 /* *** RNA collection search menu *** */
 
 struct CollItemSearch {



More information about the Bf-blender-cvs mailing list