From 11cfdfa2643bb380fc0596c737650643ce4a45be Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 15 Nov 2009 19:25:34 +0000 Subject: [PATCH] === Better support for user defined modal keymaps === Fixing/Missing RNA properties: - "virtual" property for "ANY" modifier for keymapitem - modal property for keymap - Look up modal_items in usermaps too Lazy init usermaps needs to init modal_items too. New function to initialize a user keymap (fill in modal_item and poll pointers). Operator modal keymaps now look up if there's a user defined keymap that overwrites it. Full Event UI buttons now show "Any" when modifier is set to that (instead of listing all of them). Note: Having the modifiers as boolean still doesn't express the full breath of values possible for them. There is commented code in this commit to represent them as enum, which would solve this, but make the keymap editor more cryptic. --- release/scripts/ui/space_userpref.py | 7 +- source/blender/makesrna/intern/rna_wm.c | 72 ++++++++++++++++++- source/blender/windowmanager/WM_api.h | 1 + .../windowmanager/intern/wm_event_system.c | 9 +-- .../blender/windowmanager/intern/wm_keymap.c | 67 ++++++++++++++--- 5 files changed, 137 insertions(+), 19 deletions(-) diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/ui/space_userpref.py index 18e82ae240d..3101996d355 100644 --- a/release/scripts/ui/space_userpref.py +++ b/release/scripts/ui/space_userpref.py @@ -1197,7 +1197,11 @@ class USERPREF_PT_input(bpy.types.Panel): itemcol = itemrow.column() itemcol.active = kmi.active row = itemcol.row() - row.itemR(kmi, "idname", text="") + + if km.modal: + row.itemR(kmi, "propvalue", text="") + else: + row.itemR(kmi, "idname", text="") sub = row.row() sub.scale_x = 0.6 @@ -1233,6 +1237,7 @@ class USERPREF_PT_input(bpy.types.Panel): subrow = sub.row() subrow.scale_x = 0.75 + subrow.itemR(kmi, "any") subrow.itemR(kmi, "shift") subrow.itemR(kmi, "ctrl") subrow.itemR(kmi, "alt") diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 0372e43171e..32308b456fc 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -234,6 +234,13 @@ EnumPropertyItem keymap_propvalue_items[] = { {0, "NONE", 0, "", ""}, {0, NULL, 0, NULL, NULL}}; +EnumPropertyItem keymap_modifiers_items[] = { + {KM_ANY, "ANY", 0, "Any", ""}, + {0, "NONE", 0, "None", ""}, + {1, "FIRST", 0, "First", ""}, + {2, "SECOND", 0, "Second", ""}, + {0, NULL, 0, NULL, NULL}}; + #define KMI_TYPE_KEYBOARD 0 #define KMI_TYPE_MOUSE 1 #define KMI_TYPE_TWEAK 2 @@ -411,10 +418,25 @@ static EnumPropertyItem *rna_KeyMapItem_propvalue_itemf(bContext *C, PointerRNA { wmWindowManager *wm = CTX_wm_manager(C); wmKeyConfig *kc; + wmKeyMap *km; + + /* check user keymaps */ + for(km=U.keymaps.first; km; km=km->next) { + wmKeyMapItem *ki; + for (ki=km->items.first; ki; ki=ki->next) { + if (ki == ptr->data) { + if (!km->modal_items) { + if (!WM_keymap_user_init(wm, km)) { + return keymap_propvalue_items; /* ERROR */ + } + } + + return km->modal_items; + } + } + } for(kc=wm->keyconfigs.first; kc; kc=kc->next) { - wmKeyMap *km; - for(km=kc->keymaps.first; km; km=km->next) { /* only check if it's a modal keymap */ if (km->modal_items) { @@ -428,9 +450,37 @@ static EnumPropertyItem *rna_KeyMapItem_propvalue_itemf(bContext *C, PointerRNA } } - return keymap_propvalue_items; + + return keymap_propvalue_items; /* ERROR */ } +static int rna_KeyMapItem_any_getf(PointerRNA *ptr) +{ + wmKeyMapItem *kmi = (wmKeyMapItem*)ptr->data; + + if (kmi->shift == KM_ANY && + kmi->ctrl == KM_ANY && + kmi->alt == KM_ANY && + kmi->oskey == KM_ANY) + + return 1; + else + return 0; +} + +static void rna_KeyMapItem_any_setf(PointerRNA *ptr, int value) +{ + wmKeyMapItem *kmi = (wmKeyMapItem*)ptr->data; + + if(value) { + kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= KM_ANY; + } + else { + kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= 0; + } +} + + static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr) { wmWindowManager *wm= ptr->data; @@ -762,6 +812,10 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_USER); RNA_def_property_ui_text(prop, "User Defined", "Keymap is defined by the user."); + prop= RNA_def_property(srna, "modal", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_MODAL); + RNA_def_property_ui_text(prop, "Modal Keymap", "Indicates that a keymap is used for translate modal events for an operator."); + RNA_api_keymap(srna); /* KeyMapItem */ @@ -798,20 +852,32 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_value_itemf"); RNA_def_property_ui_text(prop, "Value", ""); + prop= RNA_def_property(srna, "any", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_any_getf", "rna_KeyMapItem_any_setf"); + RNA_def_property_ui_text(prop, "Any", "Any modifier keys pressed."); + prop= RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "shift", 0); +// RNA_def_property_enum_sdna(prop, NULL, "shift"); +// RNA_def_property_enum_items(prop, keymap_modifiers_items); RNA_def_property_ui_text(prop, "Shift", "Shift key pressed."); prop= RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 0); +// RNA_def_property_enum_sdna(prop, NULL, "ctrl"); +// RNA_def_property_enum_items(prop, keymap_modifiers_items); RNA_def_property_ui_text(prop, "Ctrl", "Control key pressed."); prop= RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "alt", 0); +// RNA_def_property_enum_sdna(prop, NULL, "alt"); +// RNA_def_property_enum_items(prop, keymap_modifiers_items); RNA_def_property_ui_text(prop, "Alt", "Alt key pressed."); prop= RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "oskey", 0); +// RNA_def_property_enum_sdna(prop, NULL, "oskey"); +// RNA_def_property_enum_items(prop, keymap_modifiers_items); RNA_def_property_ui_text(prop, "OS Key", "Operating system key pressed."); prop= RNA_def_property(srna, "key_modifier", PROP_ENUM, PROP_NONE); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 554418e6483..86f68feeb9a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -105,6 +105,7 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len); wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, char *idname, int spaceid, int regionid); wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap); +int WM_keymap_user_init(struct wmWindowManager *wm, struct wmKeyMap *keymap); wmKeyMap *WM_keymap_copy_to_user(struct wmKeyMap *keymap); void WM_keymap_restore_to_default(struct wmKeyMap *keymap); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index fc453756ffa..e5508d58145 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -805,12 +805,13 @@ static int wm_event_always_pass(wmEvent *event) } /* operator exists */ -static void wm_event_modalkeymap(wmOperator *op, wmEvent *event) +static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *event) { if(op->type->modalkeymap) { + wmKeyMap *keymap= WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); wmKeyMapItem *kmi; - - for(kmi= op->type->modalkeymap->items.first; kmi; kmi= kmi->next) { + + for(kmi= keymap->items.first; kmi; kmi= kmi->next) { if(wm_eventmatch(event, kmi)) { event->type= EVT_MODAL_MAP; @@ -837,7 +838,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand wm_handler_op_context(C, handler); wm_region_mouse_co(C, event); - wm_event_modalkeymap(op, event); + wm_event_modalkeymap(C, op, event); retval= ot->modal(C, op, event); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 48262e40ea7..a9cace65206 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -88,9 +88,14 @@ void WM_keyconfig_userdef(wmWindowManager *wm) wmKeyMap *km; wmKeyMapItem *kmi; - for(km=U.keymaps.first; km; km=km->next) - for(kmi=km->items.first; kmi; kmi=kmi->next) - keymap_properties_set(kmi); + for(km=U.keymaps.first; km; km=km->next) { + /* modal keymaps don't have operator properties */ + if ((km->flag & KEYMAP_MODAL) == 0) { + for(kmi=km->items.first; kmi; kmi=kmi->next) { + keymap_properties_set(kmi); + } + } + } } static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname) @@ -295,17 +300,25 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len) buf[0]= 0; - if(kmi->shift) - strcat(buf, "Shift "); + if (kmi->shift == KM_ANY && + kmi->ctrl == KM_ANY && + kmi->alt == KM_ANY && + kmi->oskey == KM_ANY) { - if(kmi->ctrl) - strcat(buf, "Ctrl "); + strcat(buf, "Any "); + } else { + if(kmi->shift) + strcat(buf, "Shift "); - if(kmi->alt) - strcat(buf, "Alt "); + if(kmi->ctrl) + strcat(buf, "Ctrl "); - if(kmi->oskey) - strcat(buf, "Cmd "); + if(kmi->alt) + strcat(buf, "Alt "); + + if(kmi->oskey) + strcat(buf, "Cmd "); + } if(kmi->keymodifier) { strcat(buf, WM_key_event_string(kmi->keymodifier)); @@ -410,6 +423,36 @@ char *WM_key_event_operator_string(const bContext *C, const char *opname, int op /* ***************** user preferences ******************* */ +int WM_keymap_user_init(wmWindowManager *wm, wmKeyMap *keymap) +{ + wmKeyConfig *keyconf; + wmKeyMap *km; + + if(!keymap) + return 0; + + /* init from user key config */ + keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr); + if(keyconf) { + km= wm_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + if(km) { + keymap->poll= km->poll; /* lazy init */ + keymap->modal_items= km->modal_items; + return 1; + } + } + + /* or from default */ + km= wm_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + if(km) { + keymap->poll= km->poll; /* lazy init */ + keymap->modal_items= km->modal_items; + return 1; + } + + return 0; +} + wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) { wmKeyConfig *keyconf; @@ -422,6 +465,7 @@ wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) km= wm_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid); if(km) { km->poll= keymap->poll; /* lazy init */ + km->modal_items= keymap->modal_items; return km; } @@ -431,6 +475,7 @@ wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) km= wm_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); if(km) { km->poll= keymap->poll; /* lazy init */ + km->modal_items= keymap->modal_items; return km; } }