UI: Add property decorator buttons

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

See: T54951
This commit is contained in:
2018-06-16 14:48:21 +02:00
parent 8f2acda7d7
commit d8c2c63c00
5 changed files with 155 additions and 3 deletions

View File

@@ -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;