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:
@@ -964,6 +964,7 @@ void uiLayoutSetScaleX(uiLayout *layout, float scale);
|
|||||||
void uiLayoutSetScaleY(uiLayout *layout, float scale);
|
void uiLayoutSetScaleY(uiLayout *layout, float scale);
|
||||||
void uiLayoutSetEmboss(uiLayout *layout, char emboss);
|
void uiLayoutSetEmboss(uiLayout *layout, char emboss);
|
||||||
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
|
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
|
||||||
|
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep);
|
||||||
|
|
||||||
int uiLayoutGetOperatorContext(uiLayout *layout);
|
int uiLayoutGetOperatorContext(uiLayout *layout);
|
||||||
bool uiLayoutGetActive(uiLayout *layout);
|
bool uiLayoutGetActive(uiLayout *layout);
|
||||||
@@ -976,6 +977,7 @@ float uiLayoutGetScaleX(uiLayout *layout);
|
|||||||
float uiLayoutGetScaleY(uiLayout *layout);
|
float uiLayoutGetScaleY(uiLayout *layout);
|
||||||
int uiLayoutGetEmboss(uiLayout *layout);
|
int uiLayoutGetEmboss(uiLayout *layout);
|
||||||
bool uiLayoutGetPropSep(uiLayout *layout);
|
bool uiLayoutGetPropSep(uiLayout *layout);
|
||||||
|
bool uiLayoutGetPropDecorate(uiLayout *layout);
|
||||||
|
|
||||||
/* layout specifiers */
|
/* layout specifiers */
|
||||||
uiLayout *uiLayoutRow(uiLayout *layout, int align);
|
uiLayout *uiLayoutRow(uiLayout *layout, int align);
|
||||||
@@ -1257,5 +1259,7 @@ void UI_widgetbase_draw_cache_end(void);
|
|||||||
#define USE_UI_POPOVER_ONCE
|
#define USE_UI_POPOVER_ONCE
|
||||||
|
|
||||||
bool UI_but_is_tool(const uiBut *but);
|
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__ */
|
#endif /* __UI_INTERFACE_H__ */
|
||||||
|
|||||||
@@ -101,6 +101,23 @@ void ui_but_anim_flag(uiBut *but, float cfra)
|
|||||||
but->flag |= UI_BUT_DRIVEN;
|
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 */
|
/* this operator calls UI_context_active_but_prop_get */
|
||||||
WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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_set(uiBut *but, const char *str);
|
||||||
bool ui_but_anim_expression_create(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_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 */
|
/* interface_eyedropper.c */
|
||||||
struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf);
|
struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf);
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_idprop.h"
|
#include "BKE_idprop.h"
|
||||||
#include "BKE_screen.h"
|
#include "BKE_screen.h"
|
||||||
|
#include "BKE_animsys.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
|
|
||||||
@@ -63,6 +64,10 @@
|
|||||||
|
|
||||||
#include "interface_intern.h"
|
#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 *************************/
|
/************************ Structs and Defines *************************/
|
||||||
|
|
||||||
#define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \
|
#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_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
|
||||||
UI_ITEM_PROP_SEP = 1 << 3,
|
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 {
|
typedef struct uiButtonItem {
|
||||||
@@ -1477,6 +1485,18 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
|
|||||||
bool is_array;
|
bool is_array;
|
||||||
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
|
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);
|
UI_block_layout_set_current(block, layout);
|
||||||
|
|
||||||
/* retrieve info */
|
/* retrieve info */
|
||||||
@@ -1558,14 +1578,24 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
|
|||||||
|
|
||||||
/* Split the label / property. */
|
/* Split the label / property. */
|
||||||
if (use_prop_sep) {
|
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') {
|
if (name[0] == '\0') {
|
||||||
/* Ensure we get a column when text is not set. */
|
/* 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;
|
layout->space = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const PropertySubType subtype = RNA_property_subtype(prop);
|
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;
|
layout_split->space = 0;
|
||||||
uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
|
uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
|
||||||
layout_sub->space = 0;
|
layout_sub->space = 0;
|
||||||
@@ -1607,6 +1637,15 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
|
|||||||
layout->space = 0;
|
layout->space = 0;
|
||||||
name = "";
|
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. */
|
/* 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);
|
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) {
|
if (no_bg) {
|
||||||
layout->emboss = prev_emboss;
|
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->redalert = layout->redalert;
|
||||||
litem->w = layout->w;
|
litem->w = layout->w;
|
||||||
litem->emboss = layout->emboss;
|
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);
|
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);
|
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)
|
bool uiLayoutGetActive(uiLayout *layout)
|
||||||
{
|
{
|
||||||
return layout->active;
|
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 = MEM_callocN(sizeof(uiLayout), "uiLayout");
|
||||||
layout->item.type = ITEM_LAYOUT_ROOT;
|
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->x = x;
|
||||||
layout->y = y;
|
layout->y = y;
|
||||||
layout->root = root;
|
layout->root = root;
|
||||||
|
|||||||
@@ -963,6 +963,16 @@ static void rna_UILayout_property_split_set(PointerRNA *ptr, int value)
|
|||||||
uiLayoutSetPropSep(ptr->data, value);
|
uiLayoutSetPropSep(ptr->data, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rna_UILayout_property_decorate_get(PointerRNA *ptr)
|
||||||
|
{
|
||||||
|
return uiLayoutGetPropDecorate(ptr->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rna_UILayout_property_decorate_set(PointerRNA *ptr, int value)
|
||||||
|
{
|
||||||
|
uiLayoutSetPropDecorate(ptr->data, value);
|
||||||
|
}
|
||||||
|
|
||||||
#else /* RNA_RUNTIME */
|
#else /* RNA_RUNTIME */
|
||||||
|
|
||||||
static void rna_def_ui_layout(BlenderRNA *brna)
|
static void rna_def_ui_layout(BlenderRNA *brna)
|
||||||
@@ -1030,6 +1040,9 @@ static void rna_def_ui_layout(BlenderRNA *brna)
|
|||||||
|
|
||||||
prop = RNA_def_property(srna, "use_property_split", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_property_split", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_funcs(prop, "rna_UILayout_property_split_get", "rna_UILayout_property_split_set");
|
RNA_def_property_boolean_funcs(prop, "rna_UILayout_property_split_get", "rna_UILayout_property_split_set");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "use_property_decorate", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_funcs(prop, "rna_UILayout_property_decorate_get", "rna_UILayout_property_decorate_set");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_panel(BlenderRNA *brna)
|
static void rna_def_panel(BlenderRNA *brna)
|
||||||
|
|||||||
Reference in New Issue
Block a user