RNA: add UILayout.prop_with_menu function
Matches prop_with_popover, supporting menu types, useful if we want to control behavior of enum switching.
This commit is contained in:
		| @@ -1246,6 +1246,10 @@ void uiItemFullR_with_popover( | |||||||
|         uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag, |         uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag, | ||||||
|         const char *name, int icon, |         const char *name, int icon, | ||||||
|         const char *panel_type); |         const char *panel_type); | ||||||
|  | void uiItemFullR_with_menu( | ||||||
|  |         uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag, | ||||||
|  |         const char *name, int icon, | ||||||
|  |         const char *menu_type); | ||||||
| void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value); | void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value); | ||||||
| void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value); | void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value); | ||||||
| void uiItemEnumR_string_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *value, const char *name, int icon); | void uiItemEnumR_string_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *value, const char *name, int icon); | ||||||
|   | |||||||
| @@ -86,6 +86,7 @@ | |||||||
| static void ui_but_to_pixelrect(struct rcti *rect, const struct ARegion *ar, struct uiBlock *block, struct uiBut *but); | static void ui_but_to_pixelrect(struct rcti *rect, const struct ARegion *ar, struct uiBlock *block, struct uiBut *but); | ||||||
| static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *but_p); | static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *but_p); | ||||||
| static void ui_def_but_rna__panel_type(bContext *UNUSED(C), uiLayout *layout, void *but_p); | static void ui_def_but_rna__panel_type(bContext *UNUSED(C), uiLayout *layout, void *but_p); | ||||||
|  | static void ui_def_but_rna__menu_type(bContext *UNUSED(C), uiLayout *layout, void *but_p); | ||||||
|  |  | ||||||
| /* avoid unneeded calls to ui_but_value_get */ | /* avoid unneeded calls to ui_but_value_get */ | ||||||
| #define UI_BUT_VALUE_UNSET DBL_MAX | #define UI_BUT_VALUE_UNSET DBL_MAX | ||||||
| @@ -1152,7 +1153,8 @@ static bool ui_but_event_property_operator_string( | |||||||
| 		    (RNA_property_type(but_parent->rnaprop) == PROP_ENUM) && | 		    (RNA_property_type(but_parent->rnaprop) == PROP_ENUM) && | ||||||
| 		    ELEM(but_parent->menu_create_func, | 		    ELEM(but_parent->menu_create_func, | ||||||
| 		         ui_def_but_rna__menu, | 		         ui_def_but_rna__menu, | ||||||
| 		         ui_def_but_rna__panel_type)) | 		         ui_def_but_rna__panel_type, | ||||||
|  | 		         ui_def_but_rna__menu_type)) | ||||||
| 		{ | 		{ | ||||||
| 			prop_enum_value = (int)but->hardmin; | 			prop_enum_value = (int)but->hardmin; | ||||||
| 			ptr = &but_parent->rnapoin; | 			ptr = &but_parent->rnapoin; | ||||||
| @@ -3863,6 +3865,30 @@ bool ui_but_menu_draw_as_popover(const uiBut *but) | |||||||
| 	return (but->menu_create_func == ui_def_but_rna__panel_type); | 	return (but->menu_create_func == ui_def_but_rna__panel_type); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void ui_def_but_rna__menu_type(bContext *C, uiLayout *layout, void *but_p) | ||||||
|  | { | ||||||
|  | 	uiBut *but = but_p; | ||||||
|  | 	const char *menu_type = but->func_argN; | ||||||
|  | 	MenuType *mt = WM_menutype_find(menu_type, true); | ||||||
|  | 	if (mt) { | ||||||
|  | 		ui_item_menutype_func(C, layout, mt); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		char msg[256]; | ||||||
|  | 		SNPRINTF(msg, "Missing Menu: %s", menu_type); | ||||||
|  | 		uiItemL(layout, msg, ICON_NONE); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ui_but_rna_menu_convert_to_menu_type(uiBut *but, const char *menu_type) | ||||||
|  | { | ||||||
|  | 	BLI_assert(but->type == UI_BTYPE_MENU); | ||||||
|  | 	BLI_assert(but->menu_create_func == ui_def_but_rna__menu); | ||||||
|  | 	BLI_assert((void *)but->poin == but); | ||||||
|  | 	but->menu_create_func = ui_def_but_rna__menu_type; | ||||||
|  | 	but->func_argN = BLI_strdup(menu_type); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void ui_but_submenu_enable(uiBlock *block, uiBut *but) | static void ui_but_submenu_enable(uiBlock *block, uiBut *but) | ||||||
| { | { | ||||||
| 	but->flag |= UI_BUT_ICON_SUBMENU; | 	but->flag |= UI_BUT_ICON_SUBMENU; | ||||||
|   | |||||||
| @@ -486,6 +486,7 @@ extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but); | |||||||
| extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc); | extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc); | ||||||
|  |  | ||||||
| extern void ui_but_rna_menu_convert_to_panel_type(struct uiBut *but, const char *panel_type); | extern void ui_but_rna_menu_convert_to_panel_type(struct uiBut *but, const char *panel_type); | ||||||
|  | extern void ui_but_rna_menu_convert_to_menu_type(struct uiBut *but, const char *menu_type); | ||||||
| extern bool ui_but_menu_draw_as_popover(const uiBut *but); | extern bool ui_but_menu_draw_as_popover(const uiBut *but); | ||||||
|  |  | ||||||
| extern void ui_but_update(uiBut *but); | extern void ui_but_update(uiBut *but); | ||||||
| @@ -787,6 +788,7 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but); | |||||||
| void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop); | void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop); | ||||||
| void ui_layout_list_set_labels_active(uiLayout *layout); | void ui_layout_list_set_labels_active(uiLayout *layout); | ||||||
| /* menu callback */ | /* menu callback */ | ||||||
|  | void ui_item_menutype_func(struct bContext *C, struct uiLayout *layout, void *arg_mt); | ||||||
| void ui_item_paneltype_func(struct bContext *C, struct uiLayout *layout, void *arg_pt); | void ui_item_paneltype_func(struct bContext *C, struct uiLayout *layout, void *arg_pt); | ||||||
|  |  | ||||||
| /* interface_align.c */ | /* interface_align.c */ | ||||||
|   | |||||||
| @@ -2017,6 +2017,30 @@ void uiItemFullR_with_popover( | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void uiItemFullR_with_menu( | ||||||
|  |         uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon, | ||||||
|  |         const char *menu_type) | ||||||
|  | { | ||||||
|  | 	uiBlock *block = layout->root->block; | ||||||
|  | 	uiBut *but = block->buttons.last; | ||||||
|  | 	uiItemFullR(layout, ptr, prop, index, value, flag, name, icon); | ||||||
|  | 	but = but->next; | ||||||
|  | 	while (but) { | ||||||
|  | 		if (but->rnaprop == prop && but->type == UI_BTYPE_MENU) { | ||||||
|  | 			ui_but_rna_menu_convert_to_menu_type(but, menu_type); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		but = but->next; | ||||||
|  | 	} | ||||||
|  | 	if (but == NULL) { | ||||||
|  | 		const char *propname = RNA_property_identifier(prop); | ||||||
|  | 		ui_item_disabled(layout, menu_type); | ||||||
|  | 		RNA_warning( | ||||||
|  | 		        "property could not use a menu: %s.%s (%s)", | ||||||
|  | 		        RNA_struct_identifier(ptr->type), propname, menu_type); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value) | void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value) | ||||||
| { | { | ||||||
| 	if (RNA_property_type(prop) != PROP_ENUM) { | 	if (RNA_property_type(prop) != PROP_ENUM) { | ||||||
| @@ -2318,7 +2342,7 @@ void uiItemPointerR( | |||||||
| } | } | ||||||
|  |  | ||||||
| /* menu item */ | /* menu item */ | ||||||
| static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) | void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) | ||||||
| { | { | ||||||
| 	MenuType *mt = (MenuType *)arg_mt; | 	MenuType *mt = (MenuType *)arg_mt; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -142,6 +142,32 @@ static void rna_uiItemR_with_popover( | |||||||
| 	uiItemFullR_with_popover(layout, ptr, prop, -1, 0, flag, name, icon, panel_type); | 	uiItemFullR_with_popover(layout, ptr, prop, -1, 0, flag, name, icon, panel_type); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void rna_uiItemR_with_menu( | ||||||
|  |         uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, | ||||||
|  |         const char *text_ctxt, bool translate, int icon, | ||||||
|  |         bool icon_only, | ||||||
|  |         const char *menu_type) | ||||||
|  | { | ||||||
|  | 	PropertyRNA *prop = RNA_struct_find_property(ptr, propname); | ||||||
|  |  | ||||||
|  | 	if (!prop) { | ||||||
|  | 		RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	if (RNA_property_type(prop) != PROP_ENUM) { | ||||||
|  | 		RNA_warning("property is not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	int flag = 0; | ||||||
|  |  | ||||||
|  | 	flag |= (icon_only) ? UI_ITEM_R_ICON_ONLY : 0; | ||||||
|  |  | ||||||
|  | 	/* Get translated name (label). */ | ||||||
|  | 	name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate); | ||||||
|  | 	uiItemFullR_with_menu(layout, ptr, prop, -1, 0, flag, name, icon, menu_type); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static void rna_uiItemMenuEnumR( | static void rna_uiItemMenuEnumR( | ||||||
|         uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, |         uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, | ||||||
|         const char *text_ctxt, bool translate, int icon) |         const char *text_ctxt, bool translate, int icon) | ||||||
| @@ -671,6 +697,13 @@ void RNA_api_ui_layout(StructRNA *srna) | |||||||
| 	parm = RNA_def_string(func, "panel", NULL, 0, "", "Identifier of the panel"); | 	parm = RNA_def_string(func, "panel", NULL, 0, "", "Identifier of the panel"); | ||||||
| 	RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); | 	RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); | ||||||
|  |  | ||||||
|  | 	func = RNA_def_function(srna, "prop_with_menu", "rna_uiItemR_with_menu"); | ||||||
|  | 	api_ui_item_rna_common(func); | ||||||
|  | 	api_ui_item_common(func); | ||||||
|  | 	RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in tabs, no text"); | ||||||
|  | 	parm = RNA_def_string(func, "menu", NULL, 0, "", "Identifier of the menu"); | ||||||
|  | 	RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); | ||||||
|  |  | ||||||
| 	func = RNA_def_function(srna, "prop_tabs_enum", "rna_uiItemTabsEnumR"); | 	func = RNA_def_function(srna, "prop_tabs_enum", "rna_uiItemTabsEnumR"); | ||||||
| 	RNA_def_function_flag(func, FUNC_USE_CONTEXT); | 	RNA_def_function_flag(func, FUNC_USE_CONTEXT); | ||||||
| 	api_ui_item_rna_common(func); | 	api_ui_item_rna_common(func); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user