From 8055871e5be765958d11160e086c0e5589fefe48 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 29 Nov 2018 17:32:35 +1100 Subject: UI: support enum key shortcut detection Shows shortcuts in space-selector. --- source/blender/editors/interface/interface.c | 103 +++++++++++++++++++++------ 1 file changed, 81 insertions(+), 22 deletions(-) (limited to 'source') diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 6fc627d3847..aeee93b055b 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -90,6 +90,7 @@ /* prototypes. */ 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); /* avoid unneeded calls to ui_but_value_get */ #define UI_BUT_VALUE_UNSET DBL_MAX @@ -1067,12 +1068,35 @@ static bool ui_but_event_property_operator_string( "WM_OT_context_menu_enum", NULL }; - const size_t num_ops = sizeof(ctx_toggle_opnames) / sizeof(const char *); + + const char *ctx_enum_opnames[] = { + "WM_OT_context_set_enum", + NULL + }; + + int prop_enum_value = -1; + bool prop_enum_value_ok = false; + PointerRNA *ptr = &but->rnapoin; + PropertyRNA *prop = but->rnaprop; + if ((but->type == UI_BTYPE_BUT_MENU) && (but->block->handle != NULL)) { + uiBut *but_parent = but->block->handle->popup_create_vars.but; + if ((but->type == UI_BTYPE_BUT_MENU) && + but_parent && (but_parent->menu_create_func == ui_def_but_rna__menu)) + { + prop_enum_value = (int)but->hardmin; + ptr = &but->block->handle->popup_create_vars.but->rnapoin; + prop = but->block->handle->popup_create_vars.but->rnaprop; + prop_enum_value_ok = true; + } + } bool found = false; + /* Don't use the button again. */ + but = NULL; + /* this version is only for finding hotkeys for properties (which get set via context using operators) */ - if (but->rnaprop) { + if (prop) { /* to avoid massive slowdowns on property panels, for now, we only check the * hotkeys for Editor / Scene settings... * @@ -1081,40 +1105,51 @@ static bool ui_but_event_property_operator_string( // TODO: value (for enum stuff)? char *data_path = NULL; - if (but->rnapoin.id.data) { - ID *id = but->rnapoin.id.data; + if (ptr->id.data) { + ID *id = ptr->id.data; if (GS(id->name) == ID_SCR) { /* screen/editor property * NOTE: in most cases, there is actually no info for backwards tracing * how to get back to ID from the editor data we may be dealing with */ - if (RNA_struct_is_a(but->rnapoin.type, &RNA_Space)) { + if (RNA_struct_is_a(ptr->type, &RNA_Space)) { + /* data should be directly on here... */ + data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(prop)); + } + else if (RNA_struct_is_a(ptr->type, &RNA_Area)) { /* data should be directly on here... */ - data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(but->rnaprop)); + const char *prop_id = RNA_property_identifier(prop); + /* Hack since keys access 'type'. */ + if (STREQ(prop_id, "ui_type")) { + prop_id = "type"; + prop_enum_value >>= 16; + prop = RNA_struct_find_property(ptr, prop_id); + } + data_path = BLI_sprintfN("area.%s", prop_id); } else { /* special exceptions for common nested data in editors... */ - if (RNA_struct_is_a(but->rnapoin.type, &RNA_DopeSheet)) { + if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) { /* dopesheet filtering options... */ - data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(but->rnaprop)); + data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop)); } - else if (RNA_struct_is_a(but->rnapoin.type, &RNA_FileSelectParams)) { + else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) { /* Filebrowser options... */ - data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(but->rnaprop)); + data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop)); } } } else if (GS(id->name) == ID_SCE) { - if (RNA_struct_is_a(but->rnapoin.type, &RNA_ToolSettings)) { + if (RNA_struct_is_a(ptr->type, &RNA_ToolSettings)) { /* toolsettings property * NOTE: toolsettings is usually accessed directly (i.e. not through scene) */ - data_path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop); + data_path = RNA_path_from_ID_to_property(ptr, prop); } else { /* scene property */ - char *path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop); + char *path = RNA_path_from_ID_to_property(ptr, prop); if (path) { data_path = BLI_sprintfN("scene.%s", path); @@ -1123,7 +1158,7 @@ static bool ui_but_event_property_operator_string( #if 0 else { printf("ERROR in %s(): Couldn't get path for scene property - %s\n", - __func__, RNA_property_identifier(but->rnaprop)); + __func__, RNA_property_identifier(prop)); } #endif } @@ -1132,26 +1167,50 @@ static bool ui_but_event_property_operator_string( //puts("other id"); } - //printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(but->rnaprop), data_path); + //printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path); } /* we have a datapath! */ if (data_path) { - size_t i; - /* create a property to host the "datapath" property we're sending to the operators */ IDProperty *prop_path; - IDProperty *prop_path_value; IDPropertyTemplate val = {0}; prop_path = IDP_New(IDP_GROUP, &val, __func__); - prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1); - IDP_AddToGroup(prop_path, prop_path_value); + IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path", strlen(data_path) + 1)); + + const char **opnames; + int opnames_len; + + if (prop_enum_value_ok && prop && RNA_property_type(prop) == PROP_ENUM) { + opnames_len = ARRAY_SIZE(ctx_enum_opnames) - 1; + opnames = ctx_enum_opnames; + + const EnumPropertyItem *item; + bool free; + RNA_property_enum_items((bContext *)C, ptr, prop, &item, NULL, &free); + int index = RNA_enum_from_value(item, prop_enum_value); + if (index != -1) { + const char *id = item[index].identifier; + IDP_AddToGroup(prop_path, IDP_NewString(id, "value", strlen(id) + 1)); + } + else { + opnames_len = 0; /* Do nothing. */ + } + if (free) { + MEM_freeN((void *)item); + } + } + else { + opnames_len = ARRAY_SIZE(ctx_toggle_opnames) - 1; + opnames = ctx_toggle_opnames; + } /* check each until one works... */ - for (i = 0; (i < num_ops) && (ctx_toggle_opnames[i]); i++) { + + for (int i = 0; (i < opnames_len) && (opnames[i]); i++) { if (WM_key_event_operator_string( - C, ctx_toggle_opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, + C, opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, buf, buf_len)) { found = true; -- cgit v1.2.3