[Bf-blender-cvs] [219049bb3b7] master: UI: Better split layout support for checkboxes

Julian Eisel noreply at git.blender.org
Fri Apr 17 17:01:01 CEST 2020


Commit: 219049bb3b763b58e71fdf0091309136e6b513a8
Author: Julian Eisel
Date:   Fri Apr 17 16:40:25 2020 +0200
Branches: master
https://developer.blender.org/rB219049bb3b763b58e71fdf0091309136e6b513a8

UI: Better split layout support for checkboxes

Makes the following layout changes possible:
{F8473498} {F8473499} {F8473502}

The next commit will contain many layout changes to make good use of
these new possibilities. The result should be more consistent, easier to
read and should give a more organized impression. Additionally, it
should be possible to replace many sub-panels with compacter layouts.

Main changes:
* Checkboxes now respect the property split layouts
* Add support for row and column headers (i.e.
  `uiLayout.column(heading="Foo")`, `uiLayout.row(heading="Bar")`). If the
  first property added to this layout doesn't insert anything into the label
  split column, the heading is inserted there. Otherwise, it's inserted as own
  item.
* Add support for manually inserting decorators for an existing item
  (`uiLayout.prop_decorator()`). That way layout creators can manually insert
  this, which was the only way I saw to support property split layouts with a
  checkbox before the actual property. {F8471883}
* Autogenerated layouts for operator properties look bad if there are only
  checkboxes (which only use half the region width). So before creating the
  layout, we iterate over visible properties and disable split layout if all
  are booleans. I think this is fine, if needed we could also add layout hints
  to operators.
* `uiTemplateOperatorPropertyButs()` now handles macros itself, the caller
  used to be responsible for this. Code that didn't handle these so far never
  used macros I think, so this change should be invisible.
* Remove manual property split layout from autogenerated operator properties
  layout.
* Padding of checkboxes is tweaked to make their label visually more connected
  to the checkboxes.
* Support split layout for menus (should work for `uiLayout.menu()`,
  `.operator_menu_enum()`, `.prop_menu_enum()`, maybe more)

Maniphest Task: https://developer.blender.org/T65965

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

Reviewed by: Brecht Van Lommel, William Reynish, Pablo Vazques

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_anim.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_layout.c
M	source/blender/editors/interface/interface_templates.c
M	source/blender/editors/interface/interface_utils.c
M	source/blender/editors/interface/interface_widgets.c
M	source/blender/makesrna/intern/rna_ui_api.c
M	source/blender/windowmanager/intern/wm_operators.c

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 4716e7f0972..cd2e2794192 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -250,6 +250,8 @@ enum {
   UI_BUT_TEXT_RIGHT = 1 << 3,
   /** Prevent the button to show any tooltip. */
   UI_BUT_NO_TOOLTIP = 1 << 4,
+  /** Do not add the usual horizontal padding for text drawing. */
+  UI_BUT_NO_TEXT_PADDING = 1 << 5,
 
   /* Button align flag, for drawing groups together.
    * Used in 'uiBlock.flag', take care! */
@@ -1774,6 +1776,8 @@ enum {
   UI_ITEM_O_DEPRESS = 1 << 10,
   UI_ITEM_R_COMPACT = 1 << 11,
   UI_ITEM_R_CHECKBOX_INVERT = 1 << 12,
+  /** Don't add a real decorator item, just blank space. */
+  UI_ITEM_R_FORCE_BLANK_DECORATE = 1 << 13,
 };
 
 #define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X)
@@ -1784,6 +1788,9 @@ enum {
   UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = 1 << 1,
   UI_TEMPLATE_OP_PROPS_COMPACT = 1 << 2,
   UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = 1 << 3,
+  /* Disable property split for the default layout (custom ui callbacks still have full control
+   * over the layout and can enable it). */
+  UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT = 1 << 4,
 };
 
 /* used for transp checkers */
@@ -1871,7 +1878,9 @@ bool uiLayoutGetPropDecorate(uiLayout *layout);
 
 /* layout specifiers */
 uiLayout *uiLayoutRow(uiLayout *layout, bool align);
+uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading);
 uiLayout *uiLayoutColumn(uiLayout *layout, bool align);
+uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading);
 uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align);
 uiLayout *uiLayoutGridFlow(uiLayout *layout,
                            bool row_major,
@@ -2046,11 +2055,11 @@ void uiTemplateOperatorSearch(uiLayout *layout);
 void UI_but_func_menu_search(uiBut *but);
 void uiTemplateMenuSearch(uiLayout *layout);
 
-eAutoPropButsReturn uiTemplateOperatorPropertyButs(const struct bContext *C,
-                                                   uiLayout *layout,
-                                                   struct wmOperator *op,
-                                                   const eButLabelAlign label_align,
-                                                   const short flag);
+void uiTemplateOperatorPropertyButs(const struct bContext *C,
+                                    uiLayout *layout,
+                                    struct wmOperator *op,
+                                    eButLabelAlign label_align,
+                                    short flag);
 void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C);
 void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
 void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
@@ -2311,6 +2320,9 @@ void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int ic
 void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon);
 /* menu contents */
 void uiItemMContents(uiLayout *layout, const char *menuname);
+/* Decorators */
+void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index);
+void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index);
 /* value */
 void uiItemV(uiLayout *layout, const char *name, int icon, int argval);
 /* separator */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 8cccf4e5309..8ff3dc11dc7 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -641,6 +641,26 @@ static int ui_but_calc_float_precision(uiBut *but, double value)
 
 /* ************** BLOCK ENDING FUNCTION ************* */
 
+bool ui_but_rna_equals(const uiBut *a, const uiBut *b)
+{
+  return ui_but_rna_equals_ex(a, &b->rnapoin, b->rnaprop, b->rnaindex);
+}
+
+bool ui_but_rna_equals_ex(const uiBut *but,
+                          const PointerRNA *ptr,
+                          const PropertyRNA *prop,
+                          int index)
+{
+  if (but->rnapoin.data != ptr->data) {
+    return false;
+  }
+  if (but->rnaprop != prop || but->rnaindex != index) {
+    return false;
+  }
+
+  return true;
+}
+
 /* NOTE: if but->poin is allocated memory for every defbut, things fail... */
 static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
 {
@@ -649,10 +669,7 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
   if (but->retval != oldbut->retval) {
     return false;
   }
-  if (but->rnapoin.data != oldbut->rnapoin.data) {
-    return false;
-  }
-  if (but->rnaprop != oldbut->rnaprop || but->rnaindex != oldbut->rnaindex) {
+  if (!ui_but_rna_equals(but, oldbut)) {
     return false;
   }
   if (but->func != oldbut->func) {
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 15fc23bc539..877216daacc 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -28,6 +28,7 @@
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 
+#include "BLI_listbase.h"
 #include "BLI_string.h"
 #include "BLI_string_utf8.h"
 #include "BLI_utildefines.h"
@@ -114,10 +115,38 @@ void ui_but_anim_flag(uiBut *but, float cfra)
   }
 }
 
+static uiBut *ui_but_anim_decorate_find_attached_button(uiBut *but_decorate)
+{
+  uiBut *but_iter = NULL;
+
+  BLI_assert(UI_but_is_decorator(but_decorate));
+  BLI_assert(but_decorate->rnasearchpoin.data && but_decorate->rnasearchprop);
+
+  LISTBASE_CIRCULAR_BACKWARD_BEGIN (&but_decorate->block->buttons, but_iter, but_decorate->prev) {
+    if (but_iter != but_decorate && ui_but_rna_equals_ex(but_decorate,
+                                                         &but_iter->rnasearchpoin,
+                                                         but_iter->rnasearchprop,
+                                                         POINTER_AS_INT(but_iter->custom_data))) {
+      return but_iter;
+    }
+  }
+  LISTBASE_CIRCULAR_BACKWARD_END(&but_decorate->block->buttons, but_iter, but_decorate->prev);
+
+  return NULL;
+}
+
 void ui_but_anim_decorate_update_from_flag(uiBut *but)
 {
-  BLI_assert(UI_but_is_decorator(but) && but->prev);
-  int flag = but->prev->flag;
+  const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but);
+
+  if (!but_anim) {
+    printf("Could not find button with matching property to decorate (%s.%s)",
+           RNA_struct_identifier(but->rnapoin.type),
+           RNA_property_identifier(but->rnaprop));
+  }
+
+  int flag = but_anim->flag;
+
   if (flag & UI_BUT_DRIVEN) {
     but->icon = ICON_DECORATE_DRIVER;
   }
@@ -289,22 +318,26 @@ void ui_but_anim_paste_driver(bContext *C)
 void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
 {
   wmWindowManager *wm = CTX_wm_manager(C);
-  uiBut *but = arg_but;
-  but = but->prev;
+  uiBut *but_decorate = arg_but;
+  uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but_decorate);
+
+  if (!but_anim) {
+    return;
+  }
 
   /* FIXME(campbell), swapping active pointer is weak. */
-  SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+  SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active);
   wm->op_undo_depth++;
 
-  if (but->flag & UI_BUT_DRIVEN) {
+  if (but_anim->flag & UI_BUT_DRIVEN) {
     /* pass */
     /* TODO: report? */
   }
-  else if (but->flag & UI_BUT_ANIMATED_KEY) {
+  else if (but_anim->flag & UI_BUT_ANIMATED_KEY) {
     PointerRNA props_ptr;
     wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false);
     WM_operator_properties_create_ptr(&props_ptr, ot);
-    RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+    RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
     WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
     WM_operator_properties_free(&props_ptr);
   }
@@ -312,11 +345,11 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)
     PointerRNA props_ptr;
     wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false);
     WM_operator_properties_create_ptr(&props_ptr, ot);
-    RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+    RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
     WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
     WM_operator_properties_free(&props_ptr);
   }
 
-  SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+  SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active);
   wm->op_undo_depth--;
 }
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 593d176849f..c2417c86086 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -790,6 +790,11 @@ float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]);
 
 void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip);
 void ui_but_clipboard_free(void);
+bool ui_but_rna_equals(const uiBut *a, const uiBut *b);
+bool ui_but_rna_equals_ex(const uiBut *but,
+                          const PointerRNA *ptr,
+                          const PropertyRNA *prop,
+                          int index);
 uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
 uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
 
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index cbea32f179a..fa962b7742d 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -135,10 +135,11 @@ enum {
 
   UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
   UI_ITEM_PROP_SEP = 1 << 3,
+  UI_ITEM_INSIDE_PROP_SEP = 1 << 4,
   /* Show an icon button next to each property (to set keyframes, show status).
    * Enabled by default, depends on 'UI_ITEM_PROP

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list