Implementation of custom python entries in all right click menus

Hi Guys,

as one of my clients needs the possibility to have custom menu entries in the general right click menu (all over Blender: in the node editor, properties, toolbars,..) I talked with Campbell about expanding our hard coded menu a bit. This is the outcome. As I only need those two, I support currently a button_prop and a button_pointer.

{F540397}

I tested the changes with a custom script where I added a custom entry and executed an operator on click - it seems to work exactly how it's intended to. The script: {F540435}

As I'm not too experienced in rna stuff I would really appreciate any review.
Thanks very much Campbell for his open ears & help on this issue!

Reviewers: campbellbarton, mont29

Reviewed By: campbellbarton, mont29

Subscribers: sybren, mont29

Tags: #addons

Differential Revision: https://developer.blender.org/D2612
This commit is contained in:
Thomas Beck 2017-04-28 13:01:03 +02:00
parent af3f7db4ec
commit d6963630dc
2 changed files with 100 additions and 1 deletions

View File

@ -0,0 +1,81 @@
"""
Custom item in the right click menu
+++++++++++++++++++++++++++++++++++
This example enables you to insert your own menu entry into the common
right click menu that you get while hovering over a value field,
color, string, etc.
To make the example work, you have to first select an object
then right click on an user interface element (maybe a color in the
material properties) and choose "Execute custom action".
Executing the operator will then dump all values directly to a
console, so make sure to open a terminal by clicking on
"Help >> Toggle System Console" or execute Blender directly
from a terminal on your system of choice)
"""
import bpy
from bpy.types import Header, Menu, Panel
def dump(obj, text):
print('-'*40, text, '-'*40)
for attr in dir(obj):
if hasattr( obj, attr ):
print( "obj.%s = %s" % (attr, getattr(obj, attr)))
class TEST_OT_Rmb(bpy.types.Operator):
"""Right click entry test"""
bl_idname = "object.rmb_test_op"
bl_label = "Execute custom action"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
if hasattr(context, 'button_pointer'):
btn = context.button_pointer
dump(btn, 'button_pointer')
if hasattr(context, 'button_prop'):
prop = context.button_prop
dump(prop, 'button_prop')
if hasattr(context, 'button_operator'):
op = context.button_operator
dump(op, 'button_operator')
return {'FINISHED'}
# This class has to be exactly named like that to insert an entry in the right click menu
class WM_MT_button_context(Menu):
bl_label = "Add Viddyoze Tag"
def draw(self, context):
pass
def menu_func(self, context):
layout = self.layout
layout.separator()
layout.operator("object.rmb_test_op")
classes = (
TEST_OT_Rmb,
WM_MT_button_context,
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.WM_MT_button_context.append(menu_func)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)
bpy.types.WM_MT_button_context.remove(menu_func)
if __name__ == "__main__":
register()

View File

@ -6757,6 +6757,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
{
uiPopupMenu *pup;
uiLayout *layout;
MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
bool is_array, is_array_component;
uiStringInfo label = {BUT_GET_LABEL, NULL};
@ -6788,6 +6789,12 @@ static bool ui_but_menu(bContext *C, uiBut *but)
/*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */
bool is_set = RNA_property_is_set(ptr, prop);
/* set the prop and pointer data for python access to the hovered ui element; TODO, index could be supported as well*/
PointerRNA temp_ptr;
RNA_pointer_create(NULL, &RNA_Property, but->rnaprop, &temp_ptr);
uiLayoutSetContextPointer(layout,"button_prop", &temp_ptr);
uiLayoutSetContextPointer(layout,"button_pointer", ptr);
/* second slower test, saved people finding keyframe items in menus when its not possible */
if (is_anim)
is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop);
@ -7003,7 +7010,10 @@ static bool ui_but_menu(bContext *C, uiBut *but)
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
}
/* Set the operator pointer for python access */
uiLayoutSetContextPointer(layout,"button_operator", but->opptr);
uiItemS(layout);
}
@ -7050,6 +7060,14 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
mt = WM_menutype_find("WM_MT_button_context", false);
if (mt) {
Menu menu = {NULL};
menu.layout = uiLayoutColumn(layout, false);
menu.type = mt;
mt->draw(C, &menu);
}
UI_popup_menu_end(C, pup);
return true;