From dbb61988fdaa6085912dee6ab8f5569e63ef88fb Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Tue, 15 Jul 2008 07:04:31 +0000 Subject: Any script can now register a unique key combination as part of its bpy header. For a supported space type, the user may press this shortcut to invoke the script. Space types that are to support shortcuts like this should call BPY_menu_do_shortcut(...) from the event queue read method (See winqreadtextspace in drawtext.c for example) --- source/blender/include/BIF_keyval.h | 3 + source/blender/python/BPY_extern.h | 2 + source/blender/python/BPY_interface.c | 34 +++++- source/blender/python/BPY_menus.c | 35 +++++- source/blender/python/BPY_menus.h | 1 + source/blender/src/drawtext.c | 24 ++++- source/blender/src/keyval.c | 195 ++++++++++++++++++++++++++++++++++ 7 files changed, 284 insertions(+), 10 deletions(-) (limited to 'source') diff --git a/source/blender/include/BIF_keyval.h b/source/blender/include/BIF_keyval.h index 70d248ded91..9693684e425 100644 --- a/source/blender/include/BIF_keyval.h +++ b/source/blender/include/BIF_keyval.h @@ -31,6 +31,9 @@ #define BIF_KEYVAL_H char *key_event_to_string(unsigned short event); +int decode_key_string(char *str, unsigned short *key, unsigned short *qual); #endif + + diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index f6a27b80733..3a826d49542 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -91,6 +91,8 @@ extern "C" { int BPY_txt_do_python_Text( struct Text *text ); int BPY_menu_do_python( short menutype, int event ); + int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short modifiers ); + int BPY_menu_invoke( struct BPyMenu *pym, short menutype ); void BPY_run_python_script( char *filename ); int BPY_run_script(struct Script *script); void BPY_free_compiled_text( struct Text *text ); diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 360c8fd7f04..e9600e9369f 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -972,8 +972,38 @@ int BPY_run_script(Script *script) *****************************************************************************/ int BPY_menu_do_python( short menutype, int event ) { - char *argstr = NULL; BPyMenu *pym; + pym = BPyMenu_GetEntry( menutype, ( short ) event ); + return BPY_menu_invoke( pym, menutype ); +} + +/**************************************************************************** +* Description: This function executes the script by its shortcut. +* Notes: It is called by the ui code in src/???.c when a user presses an +* unassigned key combination. Scripts are searched in the BPyMenuTable, +* using the given menutype and event values to know which one to invoke. +*****************************************************************************/ +int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short qual ) +{ + BPyMenu *pym; + pym = BPyMenu_GetEntry( menutype, 0 ); + + while ( pym ) { + if ( pym->key && pym->key == key && pym->qual == qual ) { + return BPY_menu_invoke( pym, menutype ); + } + pym = pym->next; + } + + return 0; +} + +/**************************************************************************** +* Description: This function executes the script described by a menu item. +*****************************************************************************/ +int BPY_menu_invoke( BPyMenu *pym, short menutype ) +{ + char *argstr = NULL; BPySubMenu *pysm; char scriptname[21]; Script *script = NULL; @@ -981,8 +1011,6 @@ int BPY_menu_do_python( short menutype, int event ) PyGILState_STATE gilstate; char filestr[FILE_MAX]; - pym = BPyMenu_GetEntry( menutype, ( short ) event ); - if( !pym ) return 0; diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c index 08691973a92..69b50e5c47a 100644 --- a/source/blender/python/BPY_menus.c +++ b/source/blender/python/BPY_menus.c @@ -42,6 +42,7 @@ #endif #include "BKE_global.h" #include "BKE_utildefines.h" +#include "BIF_keyval.h" #include "BLI_blenlib.h" #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" /* for U.pythondir */ @@ -333,6 +334,23 @@ static void bpymenu_set_tooltip( BPyMenu * pymenu, char *tip ) return; } +static void bpymenu_set_shortcut( BPyMenu * pymenu, char *combi ) +{ + unsigned short key, qual; + + if( !pymenu ) + return; + + if (!decode_key_string(combi, &key, &qual)) { + return; /* TODO: Print some error */ + } + + pymenu->key = key; + pymenu->qual = qual; + + return; +} + /* bpymenu_AddEntry: * try to find an existing pymenu entry with the given type and name; * if found, update it with new info, otherwise create a new one and fill it. @@ -693,6 +711,7 @@ void BPyMenu_PrintAllEntries( void ) * # Blender: short int (minimal Blender version) * # Group: 'group name' (defines menu) * # Submenu: 'submenu name' related_1word_arg + * # Shortcut: Modifier+Key (optional shortcut combination for supported groups) * # Tooltip: 'tooltip for the menu' * # \"\"\" * @@ -801,13 +820,19 @@ static int bpymenu_ParseFile(FILE *file, char *fname, int is_userdir) if ((matches == 3) && (strstr(head, "Submenu:") != NULL)) { bpymenu_AddSubEntry(scriptMenu, middle, tail); } else { - /* Tooltip: 'tooltip for the menu */ + /* Shortcut: 'key+combination' */ matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail); - if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) || - (strstr(head, "Tip:") != NULL))) { - bpymenu_set_tooltip(scriptMenu, middle); + if ((matches == 3) && (strstr(head, "Shortcut:") != NULL)) { + bpymenu_set_shortcut(scriptMenu, middle); + } else { + /* Tooltip: 'tooltip for the menu */ + matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail); + if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) || + (strstr(head, "Tip:") != NULL))) { + bpymenu_set_tooltip(scriptMenu, middle); + } + parser_state = 0; } - parser_state = 0; } break; diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h index e8bca09d50e..576d7b8dcd6 100644 --- a/source/blender/python/BPY_menus.h +++ b/source/blender/python/BPY_menus.h @@ -59,6 +59,7 @@ typedef struct BPyMenu { char *name; char *filename; char *tooltip; + unsigned short key, qual; /* Registered shortcut key */ short version; /* Blender version */ int dir; /* 0: default, 1: U.pythondir */ struct BPySubMenu *submenus; diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index c76ac47ffb7..b8cf99383a0 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -81,6 +81,7 @@ #include "BSE_filesel.h" #include "BPY_extern.h" +#include "BPY_menus.h" #include "mydevice.h" #include "blendef.h" @@ -1833,10 +1834,17 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (st->showsyntax) get_format_string(st); pop_space_text(st); do_draw= 1; - do_suggest= 1; + if (suggesting && ispunct(ascii)) { + confirm_suggestion(text); + if (st->showsyntax) get_format_string(st); + do_suggest= 0; + } else { + do_suggest= 1; + } } } else if (val) { - do_suggest= -1; + do_suggest= -1; /* Note that the default label sets this to 0, + so -1 only applies to the explicit cases below */ switch (event) { case AKEY: if (G.qual & LR_ALTKEY) { @@ -2102,6 +2110,12 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case ESCKEY: do_suggest= -1; break; + case SPACEKEY: + if (suggesting) { + confirm_suggestion(text); + if (st->showsyntax) get_format_string(st); + } + break; case TABKEY: if (text && text->id.lib) { error_libdata(); @@ -2300,6 +2314,12 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } + if (event && val) { + if (BPY_menu_do_shortcut(PYMENU_TEXTPLUGIN, event, G.qual)) { + do_draw= 1; + } + } + if (last_check_time < PIL_check_seconds_timer() - 1.0) { switch (txt_file_modified(text)) { case 1: diff --git a/source/blender/src/keyval.c b/source/blender/src/keyval.c index dab4b4ae839..f59cce0da8f 100644 --- a/source/blender/src/keyval.c +++ b/source/blender/src/keyval.c @@ -27,6 +27,11 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "stdio.h" +#include "ctype.h" +#include "string.h" + +#include "BKE_global.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BIF_keyval.h" @@ -349,3 +354,193 @@ char *key_event_to_string(unsigned short event) return ""; } + +/* + * Decodes key combination strings [qual1+[qual2+[...]]]keyname + * The '+'s may be replaced by '-' or ' ' characters to support different + * formats. No additional whitespace is allowed. The keyname may be an internal + * name, like "RETKEY", or a more common name, like "Return". Decoding is case- + * insensitive. + * + * Example strings: "Ctrl+L", "ALT-ESC", "Shift A" + * + * Returns 1 if successful. + */ +int decode_key_string(char *str, unsigned short *key, unsigned short *qual) +{ + int i, prev, len, invalid=0; + + len= strlen(str); + *key= *qual= 0; + + /* Convert to upper case */ + for (i=0; i='A' && str[prev]<='Z') { + *key= str[prev]-'A'+AKEY; + } else if (str[prev]>='0' && str[prev]<='9') { + *key= str[prev]-'0'+ZEROKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev, "ZEROKEY", len-prev) || !strncmp(str+prev, "ZERO", len-prev)) { + *key= ZEROKEY; + } else if (!strncmp(str+prev, "ONEKEY", len-prev) || !strncmp(str+prev, "ONE", len-prev)) { + *key= ONEKEY; + } else if (!strncmp(str+prev, "TWOKEY", len-prev) || !strncmp(str+prev, "TWO", len-prev)) { + *key= TWOKEY; + } else if (!strncmp(str+prev, "THREEKEY", len-prev) || !strncmp(str+prev, "THREE", len-prev)) { + *key= THREEKEY; + } else if (!strncmp(str+prev, "FOURKEY", len-prev) || !strncmp(str+prev, "FOUR", len-prev)) { + *key= FOURKEY; + } else if (!strncmp(str+prev, "FIVEKEY", len-prev) || !strncmp(str+prev, "FIVE", len-prev)) { + *key= FIVEKEY; + } else if (!strncmp(str+prev, "SIZEKEY", len-prev) || !strncmp(str+prev, "SIX", len-prev)) { + *key= SIXKEY; + } else if (!strncmp(str+prev, "SEVENKEY", len-prev) || !strncmp(str+prev, "SEVEN", len-prev)) { + *key= SEVENKEY; + } else if (!strncmp(str+prev, "EIGHTKEY", len-prev) || !strncmp(str+prev, "EIGHT", len-prev)) { + *key= EIGHTKEY; + } else if (!strncmp(str+prev, "NINEKEY", len-prev) || !strncmp(str+prev, "NINE", len-prev)) { + *key= NINEKEY; + + } else if (!strncmp(str+prev, "ESCKEY", len-prev) || !strncmp(str+prev, "ESC", len-prev)) { + *key= ESCKEY; + } else if (!strncmp(str+prev, "TABKEY", len-prev) || !strncmp(str+prev, "TAB", len-prev)) { + *key= TABKEY; + } else if (!strncmp(str+prev, "RETKEY", len-prev) || !strncmp(str+prev, "RETURN", len-prev) || !strncmp(str+prev, "ENTER", len-prev)) { + *key= RETKEY; + } else if (!strncmp(str+prev, "SPACEKEY", len-prev) || !strncmp(str+prev, "SPACE", len-prev)) { + *key= SPACEKEY; + } else if (!strncmp(str+prev, "LINEFEEDKEY", len-prev) || !strncmp(str+prev, "LINEFEED", len-prev)) { + *key= LINEFEEDKEY; + } else if (!strncmp(str+prev, "BACKSPACEKEY", len-prev) || !strncmp(str+prev, "BACKSPACE", len-prev)) { + *key= BACKSPACEKEY; + } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) { + *key= DELKEY; + + } else if (!strncmp(str+prev, "SEMICOLONKEY", len-prev) || !strncmp(str+prev, "SEMICOLON", len-prev)) { + *key= SEMICOLONKEY; + } else if (!strncmp(str+prev, "PERIODKEY", len-prev) || !strncmp(str+prev, "PERIOD", len-prev)) { + *key= PERIODKEY; + } else if (!strncmp(str+prev, "COMMAKEY", len-prev) || !strncmp(str+prev, "COMMA", len-prev)) { + *key= COMMAKEY; + } else if (!strncmp(str+prev, "QUOTEKEY", len-prev) || !strncmp(str+prev, "QUOTE", len-prev)) { + *key= QUOTEKEY; + } else if (!strncmp(str+prev, "ACCENTGRAVEKEY", len-prev) || !strncmp(str+prev, "ACCENTGRAVE", len-prev)) { + *key= ACCENTGRAVEKEY; + } else if (!strncmp(str+prev, "MINUSKEY", len-prev) || !strncmp(str+prev, "MINUS", len-prev)) { + *key= MINUSKEY; + } else if (!strncmp(str+prev, "SLASHKEY", len-prev) || !strncmp(str+prev, "SLASH", len-prev)) { + *key= SLASHKEY; + } else if (!strncmp(str+prev, "BACKSLASHKEY", len-prev) || !strncmp(str+prev, "BACKSLASH", len-prev)) { + *key= BACKSLASHKEY; + } else if (!strncmp(str+prev, "EQUALKEY", len-prev) || !strncmp(str+prev, "EQUAL", len-prev)) { + *key= EQUALKEY; + } else if (!strncmp(str+prev, "LEFTBRACKETKEY", len-prev) || !strncmp(str+prev, "LEFTBRACKET", len-prev)) { + *key= LEFTBRACKETKEY; + } else if (!strncmp(str+prev, "RIGHTBRACKETKEY", len-prev) || !strncmp(str+prev, "RIGHTBRACKET", len-prev)) { + *key= RIGHTBRACKETKEY; + } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) { + *key= DELKEY; + + } else if (!strncmp(str+prev, "LEFTARROWKEY", len-prev) || !strncmp(str+prev, "LEFTARROW", len-prev)) { + *key= LEFTARROWKEY; + } else if (!strncmp(str+prev, "DOWNARROWKEY", len-prev) || !strncmp(str+prev, "DOWNARROW", len-prev)) { + *key= DOWNARROWKEY; + } else if (!strncmp(str+prev, "RIGHTARROWKEY", len-prev) || !strncmp(str+prev, "RIGHTARROW", len-prev)) { + *key= RIGHTARROWKEY; + } else if (!strncmp(str+prev, "UPARROWKEY", len-prev) || !strncmp(str+prev, "UPARROW", len-prev)) { + *key= UPARROWKEY; + + } else if (!strncmp(str+prev, "PAD", 3)) { + + if (len-prev<=4) { + + if (str[prev]>='0' && str[prev]<='9') { + *key= str[prev]-'0'+ZEROKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev+3, "PERIODKEY", len-prev-3) || !strncmp(str+prev+3, "PERIOD", len-prev-3)) { + *key= PADPERIOD; + } else if (!strncmp(str+prev+3, "SLASHKEY", len-prev-3) || !strncmp(str+prev+3, "SLASH", len-prev-3)) { + *key= PADSLASHKEY; + } else if (!strncmp(str+prev+3, "ASTERKEY", len-prev-3) || !strncmp(str+prev+3, "ASTERISK", len-prev-3)) { + *key= PADASTERKEY; + } else if (!strncmp(str+prev+3, "MINUSKEY", len-prev-3) || !strncmp(str+prev+3, "MINUS", len-prev-3)) { + *key= PADMINUS; + } else if (!strncmp(str+prev+3, "ENTERKEY", len-prev-3) || !strncmp(str+prev+3, "ENTER", len-prev-3)) { + *key= PADENTER; + } else if (!strncmp(str+prev+3, "PLUSKEY", len-prev-3) || !strncmp(str+prev+3, "PLUS", len-prev-3)) { + *key= PADPLUSKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev, "F1KEY", len-prev) || !strncmp(str+prev, "F1", len-prev)) { + *key= F1KEY; + } else if (!strncmp(str+prev, "F2KEY", len-prev) || !strncmp(str+prev, "F2", len-prev)) { + *key= F2KEY; + } else if (!strncmp(str+prev, "F3KEY", len-prev) || !strncmp(str+prev, "F3", len-prev)) { + *key= F3KEY; + } else if (!strncmp(str+prev, "F4KEY", len-prev) || !strncmp(str+prev, "F4", len-prev)) { + *key= F4KEY; + } else if (!strncmp(str+prev, "F5KEY", len-prev) || !strncmp(str+prev, "F5", len-prev)) { + *key= F5KEY; + } else if (!strncmp(str+prev, "F6KEY", len-prev) || !strncmp(str+prev, "F6", len-prev)) { + *key= F6KEY; + } else if (!strncmp(str+prev, "F7KEY", len-prev) || !strncmp(str+prev, "F7", len-prev)) { + *key= F7KEY; + } else if (!strncmp(str+prev, "F8KEY", len-prev) || !strncmp(str+prev, "F8", len-prev)) { + *key= F8KEY; + } else if (!strncmp(str+prev, "F9KEY", len-prev) || !strncmp(str+prev, "F9", len-prev)) { + *key= F9KEY; + } else if (!strncmp(str+prev, "F10KEY", len-prev) || !strncmp(str+prev, "F10", len-prev)) { + *key= F10KEY; + } else if (!strncmp(str+prev, "F11KEY", len-prev) || !strncmp(str+prev, "F11", len-prev)) { + *key= F11KEY; + } else if (!strncmp(str+prev, "F12KEY", len-prev) || !strncmp(str+prev, "F12", len-prev)) { + *key= F12KEY; + + } else if (!strncmp(str+prev, "PAUSEKEY", len-prev) || !strncmp(str+prev, "PAUSE", len-prev)) { + *key= PAUSEKEY; + } else if (!strncmp(str+prev, "INSERTKEY", len-prev) || !strncmp(str+prev, "INSERT", len-prev)) { + *key= INSERTKEY; + } else if (!strncmp(str+prev, "HOMEKEY", len-prev) || !strncmp(str+prev, "HOME", len-prev)) { + *key= HOMEKEY; + } else if (!strncmp(str+prev, "PAGEUPKEY", len-prev) || !strncmp(str+prev, "PAGEUP", len-prev)) { + *key= PAGEUPKEY; + } else if (!strncmp(str+prev, "PAGEDOWNKEY", len-prev) || !strncmp(str+prev, "PAGEDOWN", len-prev)) { + *key= PAGEDOWNKEY; + } else if (!strncmp(str+prev, "ENDKEY", len-prev) || !strncmp(str+prev, "END", len-prev)) { + *key= ENDKEY; + + } else { + invalid= 1; + } + + if (!invalid && *key) { + return 1; + } + + return 0; +} -- cgit v1.2.3