UI: support check-boxes in quick menu
Could support other RNA types, however menus don't work well in this case.
This commit is contained in:
parent
7d48a342d6
commit
6a13b6324b
|
@ -76,14 +76,17 @@ bUserMenuItem *BKE_blender_user_menu_item_add(ListBase *lb, int type)
|
|||
{
|
||||
uint size;
|
||||
|
||||
if (type == USER_MENU_TYPE_OPERATOR) {
|
||||
if (type == USER_MENU_TYPE_SEP) {
|
||||
size = sizeof(bUserMenuItem);
|
||||
}
|
||||
else if (type == USER_MENU_TYPE_OPERATOR) {
|
||||
size = sizeof(bUserMenuItem_Op);
|
||||
}
|
||||
else if (type == USER_MENU_TYPE_MENU) {
|
||||
size = sizeof(bUserMenuItem_Menu);
|
||||
}
|
||||
else if (type == USER_MENU_TYPE_SEP) {
|
||||
size = sizeof(bUserMenuItem);
|
||||
else if (type == USER_MENU_TYPE_PROP) {
|
||||
size = sizeof(bUserMenuItem_Prop);
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
|
|
|
@ -1254,6 +1254,14 @@ static void write_userdef(WriteData *wd, const UserDef *userdef)
|
|||
IDP_WriteProperty(umi_op->prop, wd);
|
||||
}
|
||||
}
|
||||
else if (umi->type == USER_MENU_TYPE_MENU) {
|
||||
const bUserMenuItem_Menu *umi_mt = (const bUserMenuItem_Menu *)umi;
|
||||
writestruct(wd, DATA, bUserMenuItem_Menu, 1, umi_mt);
|
||||
}
|
||||
else if (umi->type == USER_MENU_TYPE_PROP) {
|
||||
const bUserMenuItem_Prop *umi_pr = (const bUserMenuItem_Prop *)umi;
|
||||
writestruct(wd, DATA, bUserMenuItem_Prop, 1, umi_pr);
|
||||
}
|
||||
else {
|
||||
writestruct(wd, DATA, bUserMenuItem, 1, umi);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ struct wmMsgSubscribeValue;
|
|||
struct wmOperatorType;
|
||||
struct IDProperty;
|
||||
struct MenuType;
|
||||
struct PropertyRNA;
|
||||
|
||||
/* regions */
|
||||
void ED_region_do_listen(
|
||||
|
@ -330,6 +331,9 @@ struct bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(
|
|||
struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(
|
||||
struct ListBase *lb,
|
||||
const struct MenuType *mt);
|
||||
struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(
|
||||
struct ListBase *lb,
|
||||
const char *context_data_path, const char *prop_id, int prop_index);
|
||||
|
||||
void ED_screen_user_menu_item_add_operator(
|
||||
struct ListBase *lb, const char *ui_name,
|
||||
|
@ -337,6 +341,9 @@ void ED_screen_user_menu_item_add_operator(
|
|||
void ED_screen_user_menu_item_add_menu(
|
||||
struct ListBase *lb, const char *ui_name,
|
||||
const struct MenuType *mt);
|
||||
void ED_screen_user_menu_item_add_prop(
|
||||
ListBase *lb, const char *ui_name,
|
||||
const char *context_data_path, const char *prop_id, int prop_index);
|
||||
|
||||
void ED_screen_user_menu_item_remove(
|
||||
struct ListBase *lb, struct bUserMenuItem *umi);
|
||||
|
|
|
@ -216,12 +216,16 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
|
|||
UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL);
|
||||
}
|
||||
|
||||
static bool ui_but_is_user_menu_compatible(uiBut *but)
|
||||
static bool ui_but_is_user_menu_compatible(bContext *C, uiBut *but)
|
||||
{
|
||||
return (but->optype || UI_but_menutype_get(but));
|
||||
return (but->optype ||
|
||||
(but->rnaprop &&
|
||||
(RNA_property_type(but->rnaprop) == PROP_BOOLEAN) &&
|
||||
(WM_context_member_from_ptr(C, &but->rnapoin) != NULL)) ||
|
||||
UI_but_menutype_get(but));
|
||||
}
|
||||
|
||||
static bUserMenuItem *ui_but_user_menu_find(uiBut *but, bUserMenu *um)
|
||||
static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *um)
|
||||
{
|
||||
MenuType *mt = NULL;
|
||||
if (but->optype) {
|
||||
|
@ -229,6 +233,12 @@ static bUserMenuItem *ui_but_user_menu_find(uiBut *but, bUserMenu *um)
|
|||
return (bUserMenuItem *)ED_screen_user_menu_item_find_operator(
|
||||
&um->items, but->optype, prop, but->opcontext);
|
||||
}
|
||||
else if (but->rnaprop) {
|
||||
const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
|
||||
const char *prop_id = RNA_property_identifier(but->rnaprop);
|
||||
return (bUserMenuItem *)ED_screen_user_menu_item_find_prop(
|
||||
&um->items, member_id, prop_id, but->rnaindex);
|
||||
}
|
||||
else if ((mt = UI_but_menutype_get(but))) {
|
||||
return (bUserMenuItem *)ED_screen_user_menu_item_find_menu(
|
||||
&um->items, mt);
|
||||
|
@ -238,9 +248,9 @@ static bUserMenuItem *ui_but_user_menu_find(uiBut *but, bUserMenu *um)
|
|||
}
|
||||
}
|
||||
|
||||
static void ui_but_user_menu_add(uiBut *but, bUserMenu *um)
|
||||
static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
|
||||
{
|
||||
BLI_assert(ui_but_is_user_menu_compatible(but));
|
||||
BLI_assert(ui_but_is_user_menu_compatible(C, but));
|
||||
|
||||
char drawstr[sizeof(but->drawstr)];
|
||||
STRNCPY(drawstr, but->drawstr);
|
||||
|
@ -257,6 +267,26 @@ static void ui_but_user_menu_add(uiBut *but, bUserMenu *um)
|
|||
&um->items, drawstr,
|
||||
but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext);
|
||||
}
|
||||
else if (but->rnaprop) {
|
||||
/* Note: 'member_id' may be a path. */
|
||||
const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
|
||||
const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
|
||||
const char *member_id_data_path = member_id;
|
||||
if (data_path) {
|
||||
member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
|
||||
}
|
||||
const char *prop_id = RNA_property_identifier(but->rnaprop);
|
||||
/* Note, ignore 'drawstr', use property idname always. */
|
||||
ED_screen_user_menu_item_add_prop(
|
||||
&um->items, "",
|
||||
member_id_data_path, prop_id, but->rnaindex);
|
||||
if (data_path) {
|
||||
MEM_freeN((void *)data_path);
|
||||
}
|
||||
if (member_id != member_id_data_path) {
|
||||
MEM_freeN((void *)member_id_data_path);
|
||||
}
|
||||
}
|
||||
else if ((mt = UI_but_menutype_get(but))) {
|
||||
ED_screen_user_menu_item_add_menu(
|
||||
&um->items, drawstr,
|
||||
|
@ -268,7 +298,7 @@ static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *U
|
|||
{
|
||||
uiBut *but = arg1;
|
||||
bUserMenu *um = ED_screen_user_menu_ensure(C);
|
||||
ui_but_user_menu_add(but, um);
|
||||
ui_but_user_menu_add(C, but, um);
|
||||
}
|
||||
|
||||
static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *arg2)
|
||||
|
@ -658,7 +688,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
|
|||
}
|
||||
|
||||
/* Favorites Menu */
|
||||
if (ui_but_is_user_menu_compatible(but)) {
|
||||
if (ui_but_is_user_menu_compatible(C, but)) {
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
const int w = uiLayoutGetWidth(layout);
|
||||
uiBut *but2;
|
||||
|
@ -672,7 +702,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
|
|||
|
||||
bUserMenu *um = ED_screen_user_menu_find(C);
|
||||
if (um) {
|
||||
bUserMenuItem *umi = ui_but_user_menu_find(but, um);
|
||||
bUserMenuItem *umi = ui_but_user_menu_find(C, but, um);
|
||||
if (umi != NULL) {
|
||||
but2 = uiDefIconTextBut(
|
||||
block, UI_BTYPE_BUT, 0, ICON_CANCEL,
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Menu Type
|
||||
* \{ */
|
||||
|
@ -113,6 +115,24 @@ struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(
|
||||
struct ListBase *lb,
|
||||
const char *context_data_path, const char *prop_id, int prop_index)
|
||||
{
|
||||
for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
|
||||
if (umi->type == USER_MENU_TYPE_PROP) {
|
||||
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
|
||||
if (STREQ(context_data_path, umi_pr->context_data_path) &&
|
||||
STREQ(prop_id, umi_pr->prop_id) &&
|
||||
(prop_index == umi_pr->prop_index))
|
||||
{
|
||||
return umi_pr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ED_screen_user_menu_item_add_operator(
|
||||
ListBase *lb, const char *ui_name,
|
||||
const wmOperatorType *ot, const IDProperty *prop, short opcontext)
|
||||
|
@ -137,6 +157,17 @@ void ED_screen_user_menu_item_add_menu(
|
|||
STRNCPY(umi_mt->mt_idname, mt->idname);
|
||||
}
|
||||
|
||||
void ED_screen_user_menu_item_add_prop(
|
||||
ListBase *lb, const char *ui_name,
|
||||
const char *context_data_path, const char *prop_id, int prop_index)
|
||||
{
|
||||
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_PROP);
|
||||
STRNCPY(umi_pr->item.ui_name, ui_name);
|
||||
STRNCPY(umi_pr->context_data_path, context_data_path);
|
||||
STRNCPY(umi_pr->prop_id, prop_id);
|
||||
umi_pr->prop_index = prop_index;
|
||||
}
|
||||
|
||||
void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi)
|
||||
{
|
||||
BLI_remlink(lb, umi);
|
||||
|
@ -176,6 +207,47 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu)
|
|||
uiItemM(menu->layout, umi_mt->mt_idname, ui_name,
|
||||
ICON_NONE);
|
||||
}
|
||||
else if (umi->type == USER_MENU_TYPE_PROP) {
|
||||
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
|
||||
|
||||
char *data_path = strchr(umi_pr->context_data_path, '.');
|
||||
if (data_path) {
|
||||
*data_path = '\0';
|
||||
}
|
||||
PointerRNA ptr = CTX_data_pointer_get(C, umi_pr->context_data_path);
|
||||
if (ptr.type == NULL) {
|
||||
PointerRNA ctx_ptr;
|
||||
RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr);
|
||||
if (!RNA_path_resolve_full(&ctx_ptr, umi_pr->context_data_path, &ptr, NULL, NULL)) {
|
||||
ptr.type = NULL;
|
||||
}
|
||||
}
|
||||
if (data_path) {
|
||||
*data_path = '.';
|
||||
data_path += 1;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
if (ptr.type != NULL) {
|
||||
PropertyRNA *prop = NULL;
|
||||
PointerRNA prop_ptr = ptr;
|
||||
if ((data_path == NULL) || RNA_path_resolve_full(&ptr, data_path, &prop_ptr, NULL, NULL)) {
|
||||
prop = RNA_struct_find_property(&prop_ptr, umi_pr->prop_id);
|
||||
if (prop) {
|
||||
ok = true;
|
||||
uiItemFullR(
|
||||
menu->layout,
|
||||
&prop_ptr, prop, umi_pr->prop_index,
|
||||
0, 0, ui_name, ICON_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
char label[512];
|
||||
SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id);
|
||||
uiItemL(menu->layout, label, ICON_NONE);
|
||||
}
|
||||
}
|
||||
else if (umi->type == USER_MENU_TYPE_SEP) {
|
||||
uiItemS(menu->layout);
|
||||
}
|
||||
|
|
|
@ -465,10 +465,19 @@ typedef struct bUserMenuItem_Menu {
|
|||
char mt_idname[64];
|
||||
} bUserMenuItem_Menu;
|
||||
|
||||
typedef struct bUserMenuItem_Prop {
|
||||
bUserMenuItem item;
|
||||
char context_data_path[256];
|
||||
char prop_id[64];
|
||||
int prop_index;
|
||||
char _pad0[4];
|
||||
} bUserMenuItem_Prop;
|
||||
|
||||
enum {
|
||||
USER_MENU_TYPE_SEP = 1,
|
||||
USER_MENU_TYPE_OPERATOR = 2,
|
||||
USER_MENU_TYPE_MENU = 3,
|
||||
USER_MENU_TYPE_PROP = 4,
|
||||
};
|
||||
|
||||
typedef struct SolidLight {
|
||||
|
|
|
@ -422,6 +422,7 @@ char *WM_prop_pystring_assign(struct bContext *C, struct PointerRNA *ptr, struc
|
|||
void WM_operator_bl_idname(char *to, const char *from);
|
||||
void WM_operator_py_idname(char *to, const char *from);
|
||||
bool WM_operator_py_idname_ok_or_report(struct ReportList *reports, const char *classname, const char *idname);
|
||||
const char *WM_context_member_from_ptr(struct bContext *C, const struct PointerRNA *ptr);
|
||||
|
||||
/* *************** uilist types ******************** */
|
||||
void WM_uilisttype_init(void);
|
||||
|
|
|
@ -805,7 +805,7 @@ bool WM_operator_pystring_abbreviate(char *str, int str_len_max)
|
|||
|
||||
/* return NULL if no match is found */
|
||||
#if 0
|
||||
static const char *wm_context_member_from_ptr(bContext *C, PointerRNA *ptr)
|
||||
static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr)
|
||||
{
|
||||
/* loop over all context items and do 2 checks
|
||||
*
|
||||
|
@ -860,7 +860,7 @@ static const char *wm_context_member_from_ptr(bContext *C, PointerRNA *ptr)
|
|||
|
||||
/* use hard coded checks for now */
|
||||
|
||||
static const char *wm_context_member_from_ptr(bContext *C, PointerRNA *ptr)
|
||||
static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr)
|
||||
{
|
||||
const char *member_id = NULL;
|
||||
|
||||
|
@ -985,6 +985,11 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert
|
|||
return ret;
|
||||
}
|
||||
|
||||
const char *WM_context_member_from_ptr(bContext *C, const PointerRNA *ptr)
|
||||
{
|
||||
return wm_context_member_from_ptr(C, ptr);
|
||||
}
|
||||
|
||||
char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
|
||||
{
|
||||
char *lhs, *rhs, *ret;
|
||||
|
|
Loading…
Reference in New Issue