[Bf-blender-cvs] [d8c2c63c005] blender2.8: UI: Add property decorator buttons

Campbell Barton noreply at git.blender.org
Sat Jun 16 16:30:30 CEST 2018


Commit: d8c2c63c005b686c7489b06b889cd30cf9eeea9c
Author: Campbell Barton
Date:   Sat Jun 16 14:48:21 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBd8c2c63c005b686c7489b06b889cd30cf9eeea9c

UI: Add property decorator buttons

When use_property_split is enabled, this template adds
buttons to set keyframes, (Alternative to showing color).

See: T54951

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

M	source/blender/editors/include/UI_interface.h
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/makesrna/intern/rna_ui.c

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 876a382bb7c..0b4817c8049 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -964,6 +964,7 @@ void uiLayoutSetScaleX(uiLayout *layout, float scale);
 void uiLayoutSetScaleY(uiLayout *layout, float scale);
 void uiLayoutSetEmboss(uiLayout *layout, char emboss);
 void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
+void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep);
 
 int uiLayoutGetOperatorContext(uiLayout *layout);
 bool uiLayoutGetActive(uiLayout *layout);
@@ -976,6 +977,7 @@ float uiLayoutGetScaleX(uiLayout *layout);
 float uiLayoutGetScaleY(uiLayout *layout);
 int uiLayoutGetEmboss(uiLayout *layout);
 bool uiLayoutGetPropSep(uiLayout *layout);
+bool uiLayoutGetPropDecorate(uiLayout *layout);
 
 /* layout specifiers */
 uiLayout *uiLayoutRow(uiLayout *layout, int align);
@@ -1257,5 +1259,7 @@ void UI_widgetbase_draw_cache_end(void);
 #define USE_UI_POPOVER_ONCE
 
 bool UI_but_is_tool(const uiBut *but);
+#define UI_but_is_decorator(but) \
+	((but)->func == ui_but_anim_decorate_cb)
 
 #endif  /* __UI_INTERFACE_H__ */
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index fc0ad7e5dce..6a0dfcb5353 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -101,6 +101,23 @@ void ui_but_anim_flag(uiBut *but, float cfra)
 			but->flag |= UI_BUT_DRIVEN;
 		}
 	}
+
+	if (but->next && UI_but_is_decorator(but->next)) {
+		uiBut *but_decor = but->next;
+		int flag = but->flag;
+		if (flag & UI_BUT_DRIVEN) {
+			but_decor->icon = ICON_AUTO;
+		}
+		else if (flag & UI_BUT_ANIMATED_KEY) {
+			but_decor->icon = ICON_SPACE2;
+		}
+		else if (flag & UI_BUT_ANIMATED) {
+			but_decor->icon = ICON_SPACE3;
+		}
+		else {
+			but_decor->icon = ICON_DOT;
+		}
+	}
 }
 
 /**
@@ -299,3 +316,35 @@ void ui_but_anim_paste_driver(bContext *C)
 	/* this operator calls UI_context_active_but_prop_get */
 	WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
 }
+
+void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
+{
+	uiBut *but = arg_but;
+	but = but->prev;
+
+	/* FIXME(campbell), swapping active pointer is weak. */
+	SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+
+	if (but->flag & UI_BUT_DRIVEN) {
+		/* pass */
+		/* TODO: report? */
+	}
+	else if (but->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", false);
+		WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+		WM_operator_properties_free(&props_ptr);
+	}
+	else {
+		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", false);
+		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);
+}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 1013f39faba..15e04c5a2c7 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -814,6 +814,7 @@ bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen);
 bool ui_but_anim_expression_set(uiBut *but, const char *str);
 bool ui_but_anim_expression_create(uiBut *but, const char *str);
 void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra);
+void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy);
 
 /* interface_eyedropper.c */
 struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index ac7bbb12912..b837062671b 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -50,6 +50,7 @@
 #include "BKE_global.h"
 #include "BKE_idprop.h"
 #include "BKE_screen.h"
+#include "BKE_animsys.h"
 
 #include "RNA_access.h"
 
@@ -63,6 +64,10 @@
 
 #include "interface_intern.h"
 
+/* Show an icon button after each RNA button to use to quickly set keyframes,
+ * this is a way to display animation/driven/override status, see T54951. */
+#define UI_PROP_DECORATE
+
 /************************ Structs and Defines *************************/
 
 #define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement)                 \
@@ -132,6 +137,9 @@ enum {
 
 	UI_ITEM_BOX_ITEM  = 1 << 2, /* The item is "inside" a box item */
 	UI_ITEM_PROP_SEP  = 1 << 3,
+	/* Show an icon button next to each property (to set keyframes, show status).
+	 * Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */
+	UI_ITEM_PROP_DECORATE = 1 << 4,
 };
 
 typedef struct uiButtonItem {
@@ -1477,6 +1485,18 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
 	bool is_array;
 	const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
 
+#ifdef UI_PROP_DECORATE
+	struct {
+		bool use_prop_decorate;
+		uiLayout *layout;
+		uiBut *but;
+	} ui_decorate = {
+		.use_prop_decorate = (
+		        ((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) &&
+		        (use_prop_sep && ptr->id.data && id_can_have_animdata(ptr->id.data))),
+	};
+#endif  /* UI_PROP_DECORATE */
+
 	UI_block_layout_set_current(block, layout);
 
 	/* retrieve info */
@@ -1558,14 +1578,24 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
 
 	/* Split the label / property. */
 	if (use_prop_sep) {
+		uiLayout *layout_row = NULL;
+#ifdef UI_PROP_DECORATE
+		if (ui_decorate.use_prop_decorate) {
+			layout_row = uiLayoutRow(layout, true);
+			layout_row->space = 0;
+		}
+#endif  /* UI_PROP_DECORATE */
+
 		if (name[0] == '\0') {
 			/* Ensure we get a column when text is not set. */
-			layout = uiLayoutColumn(layout, true);
+			layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
 			layout->space = 0;
 		}
 		else {
 			const PropertySubType subtype = RNA_property_subtype(prop);
-			uiLayout *layout_split = uiLayoutSplit(layout, UI_ITEM_PROP_SEP_DIVIDE, true);
+			uiLayout *layout_split = uiLayoutSplit(
+			        layout_row ? layout_row : layout,
+			        UI_ITEM_PROP_SEP_DIVIDE, true);
 			layout_split->space = 0;
 			uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
 			layout_sub->space = 0;
@@ -1607,6 +1637,15 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
 			layout->space = 0;
 			name = "";
 		}
+
+#ifdef UI_PROP_DECORATE
+		if (ui_decorate.use_prop_decorate) {
+			ui_decorate.layout = uiLayoutColumn(layout_row, true);
+			ui_decorate.layout->space = 0;
+			UI_block_layout_set_current(block, layout);
+			ui_decorate.but = block->buttons.last;
+		}
+#endif  /* UI_PROP_DECORATE */
 	}
 	/* End split. */
 
@@ -1655,6 +1694,39 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
 		UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
 	}
 
+#ifdef UI_PROP_DECORATE
+	if (ui_decorate.use_prop_decorate) {
+		const bool is_anim = RNA_property_animateable(ptr, prop);
+		uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first;
+		uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false);
+		layout_col->space = 0;
+		layout_col->emboss = UI_EMBOSS_NONE;
+		int i;
+		for (i = 0; but_decorate; i++) {
+			/* The icons are set in 'ui_but_anim_flag' */
+			if (is_anim) {
+				but = uiDefIconBut(
+				        block, UI_BTYPE_BUT, 0, ICON_DOT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+				        NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Animate property"));
+				UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL);
+			}
+			else {
+				/* We may show other information here in future, for now use empty space. */
+				but = uiDefIconBut(
+				        block, UI_BTYPE_BUT, 0, ICON_BLANK1, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+				        NULL, 0.0, 0.0, 0.0, 0.0, "");
+				but->flag |= UI_BUT_DISABLED;
+			}
+			/* Order the decorator after the button we decorate, this is used so we can always
+			 * do a quick lookup. */
+			BLI_remlink(&block->buttons, but);
+			BLI_insertlinkafter(&block->buttons, but_decorate, but);
+			but_decorate = but->next;
+		}
+		BLI_assert(len ? i < len : i == 1);
+	}
+#endif  /* UI_PROP_DECORATE */
+
 	if (no_bg) {
 		layout->emboss = prev_emboss;
 	}
@@ -3435,7 +3507,7 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali
 	litem->redalert = layout->redalert;
 	litem->w = layout->w;
 	litem->emboss = layout->emboss;
-	litem->item.flag = (layout->item.flag & UI_ITEM_PROP_SEP);
+	litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE));
 	BLI_addtail(&layout->items, litem);
 }
 
@@ -3700,6 +3772,16 @@ void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
 	SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP);
 }
 
+bool uiLayoutGetPropDecorate(uiLayout *layout)
+{
+	return (layout->item.flag & UI_ITEM_PROP_DECORATE) != 0;
+}
+
+void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
+{
+	SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_DECORATE);
+}
+
 bool uiLayoutGetActive(uiLayout *layout)
 {
 	return layout->active;
@@ -4002,6 +4084,9 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s
 	layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
 	layout->item.type = ITEM_LAYOUT_ROOT;
 
+	/* Only used when 'UI_ITEM_PROP_SEP' is set. */
+	layout->item.flag = UI_ITEM_PROP_DECORATE;
+
 	layout->x = x;
 	layout->y = y;
 	layout->root = root;
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 8083ae35dc1..70aa4709d8c 100644
--- a/source/blender/makesrna/intern/rna_ui

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list