diff options
Diffstat (limited to 'source')
19 files changed, 1024 insertions, 465 deletions
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 8b4bbbd3c83..7e2097d1233 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -330,28 +330,45 @@ static int handle_subversion_warning(Main *main) return 1; } +static void keymap_item_free(wmKeyMapItem *kmi) +{ + if(kmi->properties) { + IDP_FreeProperty(kmi->properties); + MEM_freeN(kmi->properties); + } + if(kmi->ptr) + MEM_freeN(kmi->ptr); +} + void BKE_userdef_free(void) { wmKeyMap *km; wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; - for(km=U.keymaps.first; km; km=km->next) { - for(kmi=km->items.first; kmi; kmi=kmi->next) { - if(kmi->properties) { - IDP_FreeProperty(kmi->properties); - MEM_freeN(kmi->properties); + for(km=U.user_keymaps.first; km; km=km->next) { + for(kmdi=km->diff_items.first; kmdi; kmdi=kmdi->next) { + if(kmdi->add_item) { + keymap_item_free(kmdi->add_item); + MEM_freeN(kmdi->add_item); + } + if(kmdi->remove_item) { + keymap_item_free(kmdi->remove_item); + MEM_freeN(kmdi->remove_item); } - if(kmi->ptr) - MEM_freeN(kmi->ptr); } + for(kmi=km->items.first; kmi; kmi=kmi->next) + keymap_item_free(kmi); + + BLI_freelistN(&km->diff_items); BLI_freelistN(&km->items); } BLI_freelistN(&U.uistyles); BLI_freelistN(&U.uifonts); BLI_freelistN(&U.themes); - BLI_freelistN(&U.keymaps); + BLI_freelistN(&U.user_keymaps); BLI_freelistN(&U.addons); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 44c8ca97be9..bd12677485c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4726,6 +4726,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) wm->keyconfigs.first= wm->keyconfigs.last= NULL; wm->defaultconf= NULL; + wm->addonconf= NULL; + wm->userconf= NULL; wm->jobs.first= wm->jobs.last= NULL; wm->drags.first= wm->drags.last= NULL; @@ -11762,33 +11764,57 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_library(fd, main); /* only init users */ } +static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi) +{ + kmi->properties= newdataadr(fd, kmi->properties); + if(kmi->properties) + IDP_DirectLinkProperty(kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + kmi->ptr= NULL; + kmi->flag &= ~KMI_UPDATE; +} static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) { UserDef *user; wmKeyMap *keymap; wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; bfd->user= user= read_struct(fd, bhead, "user def"); /* read all data into fd->datamap */ bhead= read_data_into_oldnewmap(fd, bhead, "user def"); + if(user->keymaps.first) { + /* backwards compatibility */ + user->user_keymaps= user->keymaps; + user->keymaps.first= user->keymaps.last= NULL; + } + link_list(fd, &user->themes); - link_list(fd, &user->keymaps); + link_list(fd, &user->user_keymaps); link_list(fd, &user->addons); - for(keymap=user->keymaps.first; keymap; keymap=keymap->next) { + for(keymap=user->user_keymaps.first; keymap; keymap=keymap->next) { keymap->modal_items= NULL; keymap->poll= NULL; + keymap->flag &= ~KEYMAP_UPDATE; + link_list(fd, &keymap->diff_items); link_list(fd, &keymap->items); - for(kmi=keymap->items.first; kmi; kmi=kmi->next) { - kmi->properties= newdataadr(fd, kmi->properties); - if(kmi->properties) - IDP_DirectLinkProperty(kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - kmi->ptr= NULL; + + for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) { + kmdi->remove_item= newdataadr(fd, kmdi->remove_item); + kmdi->add_item= newdataadr(fd, kmdi->add_item); + + if(kmdi->remove_item) + direct_link_keymapitem(fd, kmdi->remove_item); + if(kmdi->add_item) + direct_link_keymapitem(fd, kmdi->add_item); } + + for(kmi=keymap->items.first; kmi; kmi=kmi->next) + direct_link_keymapitem(fd, kmi); } // XXX diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index bf86527b9d3..7d65248c0e9 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -717,11 +717,19 @@ static void write_renderinfo(WriteData *wd, Main *mainvar) /* for renderdeamon } } +static void write_keymapitem(WriteData *wd, wmKeyMapItem *kmi) +{ + writestruct(wd, DATA, "wmKeyMapItem", 1, kmi); + if(kmi->properties) + IDP_WriteProperty(kmi->properties, wd); +} + static void write_userdef(WriteData *wd) { bTheme *btheme; wmKeyMap *keymap; wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; bAddon *bext; uiStyle *style; @@ -730,15 +738,19 @@ static void write_userdef(WriteData *wd) for(btheme= U.themes.first; btheme; btheme=btheme->next) writestruct(wd, DATA, "bTheme", 1, btheme); - for(keymap= U.keymaps.first; keymap; keymap=keymap->next) { + for(keymap= U.user_keymaps.first; keymap; keymap=keymap->next) { writestruct(wd, DATA, "wmKeyMap", 1, keymap); - for(kmi=keymap->items.first; kmi; kmi=kmi->next) { - writestruct(wd, DATA, "wmKeyMapItem", 1, kmi); - - if(kmi->properties) - IDP_WriteProperty(kmi->properties, wd); + for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) { + writestruct(wd, DATA, "wmKeyMapDiffItem", 1, kmdi); + if(kmdi->remove_item) + write_keymapitem(wd, kmdi->remove_item); + if(kmdi->add_item) + write_keymapitem(wd, kmdi->add_item); } + + for(kmi=keymap->items.first; kmi; kmi=kmi->next) + write_keymapitem(wd, kmi); } for(bext= U.addons.first; bext; bext=bext->next) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b3272a2e3d4..d8d8354b0b9 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4067,7 +4067,6 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) /* complex code to change name of button */ if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) { - wmKeyMap *km= NULL; char *butstr_orig; // XXX but->str changed... should not, remove the hotkey from it @@ -4080,10 +4079,6 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) but->str= but->strdata; ui_check_but(but); - - /* set the keymap editable else the key wont save */ - WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, 1, &km); - WM_keymap_copy_to_user(km); } else { /* shortcut was removed */ @@ -4095,6 +4090,7 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) { + wmWindowManager *wm= CTX_wm_manager(C); uiBlock *block; uiBut *but = (uiBut *)arg; wmKeyMap *km; @@ -4107,7 +4103,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) kmi = WM_keymap_item_find_id(km, kmi_id); - RNA_pointer_create(NULL, &RNA_KeyMapItem, kmi, &ptr); + RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetHandleFunc(block, but_shortcut_name_func, but); @@ -4126,6 +4122,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) { + wmWindowManager *wm= CTX_wm_manager(C); uiBlock *block; uiBut *but = (uiBut *)arg; wmKeyMap *km; @@ -4134,19 +4131,25 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) uiLayout *layout; uiStyle *style= U.uistyles.first; IDProperty *prop= (but->opptr)? but->opptr->data: NULL; + int kmi_id; /* XXX this guess_opname can potentially return a different keymap than being found on adding later... */ km = WM_keymap_guess_opname(C, but->optype->idname); kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0); + kmi_id = kmi->id; - if (prop) { + /* copy properties, prop can be NULL for reset */ + if(prop) prop= IDP_CopyProperty(prop); - } - - /* prop can be NULL */ WM_keymap_properties_reset(kmi, prop); - RNA_pointer_create(NULL, &RNA_KeyMapItem, kmi, &ptr); + /* update and get pointers again */ + WM_keyconfig_update(wm); + + km = WM_keymap_guess_opname(C, but->optype->idname); + kmi = WM_keymap_item_find_id(km, kmi_id); + + RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetHandleFunc(block, but_shortcut_name_func, but); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 32e87b3a793..f3db6ad11ae 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1425,7 +1425,7 @@ void init_userdef_do_versions(void) if (bmain->versionfile < 250 || (bmain->versionfile == 250 && bmain->subversionfile < 8)) { wmKeyMap *km; - for(km=U.keymaps.first; km; km=km->next) { + for(km=U.user_keymaps.first; km; km=km->next) { if (strcmp(km->idname, "Armature_Sketch")==0) strcpy(km->idname, "Armature Sketch"); else if (strcmp(km->idname, "View3D")==0) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index aa6da3aaeca..a555a196060 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -341,7 +341,8 @@ typedef struct UserDef { struct ListBase themes; struct ListBase uifonts; struct ListBase uistyles; - struct ListBase keymaps; + struct ListBase keymaps; /* deprecated in favor of user_keymaps */ + struct ListBase user_keymaps; struct ListBase addons; char keyconfigstr[64]; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 31e59f18626..1f0ae28a00d 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -144,7 +144,9 @@ typedef struct wmWindowManager { ListBase drags; /* active dragged items */ ListBase keyconfigs; /* known key configurations */ - struct wmKeyConfig *defaultconf; /* default configuration, not saved */ + struct wmKeyConfig *defaultconf; /* default configuration */ + struct wmKeyConfig *addonconf; /* addon configuration */ + struct wmKeyConfig *userconf; /* user configuration */ ListBase timers; /* active timers */ struct wmTimer *autosavetimer; /* timer for auto save */ @@ -239,15 +241,26 @@ typedef struct wmKeyMapItem { struct PointerRNA *ptr; /* rna pointer to access properties */ } wmKeyMapItem; +/* used instead of wmKeyMapItem for diff keymaps */ +typedef struct wmKeyMapDiffItem { + struct wmKeyMapDiffItem *next, *prev; + + wmKeyMapItem *remove_item; + wmKeyMapItem *add_item; +} wmKeyMapDiffItem; + /* wmKeyMapItem.flag */ -#define KMI_INACTIVE 1 -#define KMI_EXPANDED 2 +#define KMI_INACTIVE 1 +#define KMI_EXPANDED 2 +#define KMI_USER_MODIFIED 4 +#define KMI_UPDATE 8 /* stored in WM, the actively used keymaps */ typedef struct wmKeyMap { struct wmKeyMap *next, *prev; ListBase items; + ListBase diff_items; char idname[64]; /* global editor keymaps, or for more per space/region */ short spaceid; /* same IDs as in DNA_space_types.h */ @@ -263,9 +276,12 @@ typedef struct wmKeyMap { /* wmKeyMap.flag */ #define KEYMAP_MODAL 1 /* modal map, not using operatornames */ -#define KEYMAP_USER 2 /* user created keymap */ +#define KEYMAP_USER 2 /* user keymap */ #define KEYMAP_EXPANDED 4 #define KEYMAP_CHILDREN_EXPANDED 8 +#define KEYMAP_DIFF 16 /* diff keymap for user preferences */ +#define KEYMAP_USER_MODIFIED 32 /* keymap has user modifications */ +#define KEYMAP_UPDATE 64 typedef struct wmKeyConfig { struct wmKeyConfig *next, *prev; diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 9175806e2bb..c0ae7b02b1a 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -238,9 +238,12 @@ void RNA_api_image(struct StructRNA *srna); void RNA_api_operator(struct StructRNA *srna); void RNA_api_macro(struct StructRNA *srna); void RNA_api_keyconfig(struct StructRNA *srna); +void RNA_api_keyconfigs(struct StructRNA *srna); void RNA_api_keyingset(struct StructRNA *srna); void RNA_api_keymap(struct StructRNA *srna); +void RNA_api_keymaps(struct StructRNA *srna); void RNA_api_keymapitem(struct StructRNA *srna); +void RNA_api_keymapitems(struct StructRNA *srna); void RNA_api_area(struct StructRNA *srna); void RNA_api_main(struct StructRNA *srna); void RNA_api_material(StructRNA *srna); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index b3d8bc8ea18..29cfc695911 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1409,7 +1409,7 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) prop= RNA_def_property(srna, "layers_zmask", PROP_BOOLEAN, PROP_LAYER); RNA_def_property_boolean_sdna(prop, NULL, "lay_zmask", 1); RNA_def_property_array(prop, 20); - RNA_def_property_ui_text(prop, "Zmask Layers", "Zmask scene layers"); + RNA_def_property_ui_text(prop, "Zmask Layers", "Zmask scene layers for solid faces"); if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index a1a99c34e70..b3dbafeab7d 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2795,12 +2795,6 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_range(prop, 0, 32); RNA_def_property_ui_text(prop, "Wheel Scroll Lines", "The number of lines scrolled at a time with the mouse wheel"); - /* U.keymaps - custom keymaps that have been edited from default configs */ - prop= RNA_def_property(srna, "edited_keymaps", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "keymaps", NULL); - RNA_def_property_struct_type(prop, "KeyMap"); - RNA_def_property_ui_text(prop, "Edited Keymaps", ""); - prop= RNA_def_property(srna, "active_keyconfig", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "keyconfigstr"); RNA_def_property_ui_text(prop, "Key Config", "The name of the active key configuration"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index a046be59ab5..307cf0e175a 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -578,22 +578,6 @@ static EnumPropertyItem *rna_KeyMapItem_propvalue_itemf(bContext *C, PointerRNA wmKeyConfig *kc; wmKeyMap *km; - /* check user keymaps */ - for(km=U.keymaps.first; km; km=km->next) { - wmKeyMapItem *kmi; - for (kmi=km->items.first; kmi; kmi=kmi->next) { - if (kmi == 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) { for(km=kc->keymaps.first; km; km=km->next) { /* only check if it's a modal keymap */ @@ -654,12 +638,13 @@ static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_KeyConfig, kc); } -static void rna_WindowManager_active_keyconfig_set(PointerRNA *UNUSED(ptr), PointerRNA value) +static void rna_WindowManager_active_keyconfig_set(PointerRNA *ptr, PointerRNA value) { + wmWindowManager *wm= ptr->data; wmKeyConfig *kc= value.data; if(kc) - BLI_strncpy(U.keyconfigstr, kc->idname, sizeof(U.keyconfigstr)); + WM_keyconfig_set_active(wm, kc->idname); } static void rna_wmKeyMapItem_idname_get(PointerRNA *ptr, char *value) @@ -1130,93 +1115,6 @@ static StructRNA* rna_MacroOperator_refine(PointerRNA *opr) return (op->type && op->type->ext.srna)? op->type->ext.srna: &RNA_Macro; } -static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) -{ -// wmWindowManager *wm = CTX_wm_manager(C); - char idname_bl[OP_MAX_TYPENAME]; - int modifier= 0; - - /* only on non-modal maps */ - if (km->flag & KEYMAP_MODAL) { - BKE_report(reports, RPT_ERROR, "Not a non-modal keymap."); - return NULL; - } - - WM_operator_bl_idname(idname_bl, idname); - - if(shift) modifier |= KM_SHIFT; - if(ctrl) modifier |= KM_CTRL; - if(alt) modifier |= KM_ALT; - if(oskey) modifier |= KM_OSKEY; - - if(any) modifier = KM_ANY; - - return WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); -} - -static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, bContext *C, ReportList *reports, const char *propvalue_str, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) -{ - wmWindowManager *wm = CTX_wm_manager(C); - int modifier= 0; - int propvalue = 0; - - /* only modal maps */ - if ((km->flag & KEYMAP_MODAL) == 0) { - BKE_report(reports, RPT_ERROR, "Not a modal keymap."); - return NULL; - } - - if (!km->modal_items) { - if(!WM_keymap_user_init(wm, km)) { - BKE_report(reports, RPT_ERROR, "User defined keymap doesn't correspond to a system keymap."); - return NULL; - } - } - - if (!km->modal_items) { - BKE_report(reports, RPT_ERROR, "No property values defined."); - return NULL; - } - - - if(RNA_enum_value_from_id(km->modal_items, propvalue_str, &propvalue)==0) { - BKE_report(reports, RPT_WARNING, "Property value not in enumeration."); - } - - if(shift) modifier |= KM_SHIFT; - if(ctrl) modifier |= KM_CTRL; - if(alt) modifier |= KM_ALT; - if(oskey) modifier |= KM_OSKEY; - - if(any) modifier = KM_ANY; - - return WM_modalkeymap_add_item(km, type, value, modifier, keymodifier, propvalue); -} - -static wmKeyMap *rna_keymap_new(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid, int modal) -{ - if (modal == 0) { - return WM_keymap_find(keyconf, idname, spaceid, regionid); - } else { - return WM_modalkeymap_add(keyconf, idname, NULL); /* items will be lazy init */ - } -} - -static wmKeyMap *rna_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid) -{ - return WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); -} - -static wmKeyMap *rna_keymap_find_modal(wmKeyConfig *UNUSED(keyconf), const char *idname) -{ - wmOperatorType *ot = WM_operatortype_find(idname, 0); - - if (!ot) - return NULL; - else - return ot->modalkeymap; -} - /* just to work around 'const char *' warning and to ensure this is a python op */ static void rna_Operator_bl_idname_set(PointerRNA *ptr, const char *value) { @@ -1242,6 +1140,12 @@ static void rna_Operator_bl_description_set(PointerRNA *ptr, const char *value) else assert(!"setting the bl_description on a non-builtin operator"); } +static void rna_KeyMapItem_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + wmKeyMapItem *kmi= ptr->data; + WM_keyconfig_update_tag(NULL, kmi); +} + #else /* RNA_RUNTIME */ static void rna_def_operator(BlenderRNA *brna) @@ -1566,9 +1470,6 @@ static void rna_def_wm_keyconfigs(BlenderRNA *brna, PropertyRNA *cprop) StructRNA *srna; PropertyRNA *prop; - FunctionRNA *func; - PropertyRNA *parm; - RNA_def_property_srna(cprop, "KeyConfigurations"); srna= RNA_def_struct(brna, "KeyConfigurations", NULL); RNA_def_struct_sdna(srna, "wmWindowManager"); @@ -1578,23 +1479,24 @@ static void rna_def_wm_keyconfigs(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_struct_type(prop, "KeyConfig"); RNA_def_property_pointer_funcs(prop, "rna_WindowManager_active_keyconfig_get", "rna_WindowManager_active_keyconfig_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Active KeyConfig", "Active wm KeyConfig"); + RNA_def_property_ui_text(prop, "Active KeyConfig", "Active key configuration (preset)"); prop= RNA_def_property(srna, "default", PROP_POINTER, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "defaultconf"); RNA_def_property_struct_type(prop, "KeyConfig"); - RNA_def_property_ui_text(prop, "Default Key Configuration", ""); + RNA_def_property_ui_text(prop, "Default Key Configuration", "Default builtin key configuration"); + + prop= RNA_def_property(srna, "addon", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "addonconf"); + RNA_def_property_struct_type(prop, "KeyConfig"); + RNA_def_property_ui_text(prop, "Addon Key Configuration", "Key configuration that can be extended by addons, and is added to the active configuration when handling events"); + + prop= RNA_def_property(srna, "user", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "userconf"); + RNA_def_property_struct_type(prop, "KeyConfig"); + RNA_def_property_ui_text(prop, "User Key Configuration", "Final key configuration that combines keymaps from the active and addon configurations, and can be edited by the user"); - /* funcs */ - func= RNA_def_function(srna, "new", "WM_keyconfig_new_user"); // add_keyconfig - parm= RNA_def_string(func, "name", "", 0, "Name", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Added key configuration."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "remove", "WM_keyconfig_remove"); // remove_keyconfig - parm= RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Removed key configuration."); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_api_keyconfigs(srna); } static void rna_def_windowmanager(BlenderRNA *brna) @@ -1631,107 +1533,30 @@ static void rna_def_windowmanager(BlenderRNA *brna) static void rna_def_keymap_items(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; -// PropertyRNA *prop; - - FunctionRNA *func; - PropertyRNA *parm; RNA_def_property_srna(cprop, "KeyMapItems"); srna= RNA_def_struct(brna, "KeyMapItems", NULL); RNA_def_struct_sdna(srna, "wmKeyMap"); RNA_def_struct_ui_text(srna, "KeyMap Items", "Collection of keymap items"); - func= RNA_def_function(srna, "new", "rna_KeyMap_item_new"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); - parm= RNA_def_string(func, "idname", "", 0, "Operator Identifier", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "type", event_type_items, 0, "Type", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "value", event_value_items, 0, "Value", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_boolean(func, "any", 0, "Any", ""); - RNA_def_boolean(func, "shift", 0, "Shift", ""); - RNA_def_boolean(func, "ctrl", 0, "Ctrl", ""); - RNA_def_boolean(func, "alt", 0, "Alt", ""); - RNA_def_boolean(func, "oskey", 0, "OS Key", ""); - RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); - parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "new_modal", "rna_KeyMap_item_new_modal"); - RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS); - parm= RNA_def_string(func, "propvalue", "", 0, "Property Value", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "type", event_type_items, 0, "Type", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "value", event_value_items, 0, "Value", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_boolean(func, "any", 0, "Any", ""); - RNA_def_boolean(func, "shift", 0, "Shift", ""); - RNA_def_boolean(func, "ctrl", 0, "Ctrl", ""); - RNA_def_boolean(func, "alt", 0, "Alt", ""); - RNA_def_boolean(func, "oskey", 0, "OS Key", ""); - RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); - parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "remove", "WM_keymap_remove_item"); - parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - - func= RNA_def_function(srna, "from_id", "WM_keymap_item_find_id"); - parm= RNA_def_property(func, "id", PROP_INT, PROP_NONE); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_property_ui_text(parm, "id", "ID of the item"); - parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); - RNA_def_function_return(func, parm); - + RNA_api_keymapitems(srna); } static void rna_def_wm_keymaps(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - //PropertyRNA *prop; - - FunctionRNA *func; - PropertyRNA *parm; - RNA_def_property_srna(cprop, "KeyMaps"); srna= RNA_def_struct(brna, "KeyMaps", NULL); RNA_def_struct_sdna(srna, "wmKeyConfig"); RNA_def_struct_ui_text(srna, "Key Maps", "Collection of keymaps"); - func= RNA_def_function(srna, "new", "rna_keymap_new"); // add_keymap - parm= RNA_def_string(func, "name", "", 0, "Name", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_enum(func, "space_type", space_type_items, SPACE_EMPTY, "Space Type", ""); - RNA_def_enum(func, "region_type", region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); - RNA_def_boolean(func, "modal", 0, "Modal", ""); - parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Added key map."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "find", "rna_keymap_find"); // find_keymap - parm= RNA_def_string(func, "name", "", 0, "Name", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_enum(func, "space_type", space_type_items, SPACE_EMPTY, "Space Type", ""); - RNA_def_enum(func, "region_type", region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); - parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Corresponding key map."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "find_modal", "rna_keymap_find_modal"); // find_keymap_modal - parm= RNA_def_string(func, "name", "", 0, "Operator Name", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Corresponding key map."); - RNA_def_function_return(func, parm); - + RNA_api_keymaps(srna); } static void rna_def_keyconfig(BlenderRNA *brna) { StructRNA *srna; - // FunctionRNA *func; - // PropertyRNA *parm; PropertyRNA *prop; static EnumPropertyItem map_type_items[] = { @@ -1794,8 +1619,8 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Items", "Items in the keymap, linking an operator to an input event"); rna_def_keymap_items(brna, prop); - prop= RNA_def_property(srna, "is_user_defined", PROP_BOOLEAN, PROP_NEVER_NULL); - RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_USER); + prop= RNA_def_property(srna, "is_user_modified", PROP_BOOLEAN, PROP_NEVER_NULL); + RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_USER_MODIFIED); RNA_def_property_ui_text(prop, "User Defined", "Keymap is defined by the user"); prop= RNA_def_property(srna, "is_modal", PROP_BOOLEAN, PROP_NONE); @@ -1826,6 +1651,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Identifier", "Identifier of operator to call on input event"); RNA_def_property_string_funcs(prop, "rna_wmKeyMapItem_idname_get", "rna_wmKeyMapItem_idname_length", "rna_wmKeyMapItem_idname_set"); RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -1836,62 +1662,73 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_struct_type(prop, "OperatorProperties"); RNA_def_property_pointer_funcs(prop, "rna_KeyMapItem_properties_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Properties", "Properties to set when the operator is called"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "map_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "maptype"); RNA_def_property_enum_items(prop, map_type_items); RNA_def_property_enum_funcs(prop, "rna_wmKeyMapItem_map_type_get", "rna_wmKeyMapItem_map_type_set", NULL); RNA_def_property_ui_text(prop, "Map Type", "Type of event mapping"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, event_type_items); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_type_itemf"); RNA_def_property_ui_text(prop, "Type", "Type of event"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "value", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "val"); RNA_def_property_enum_items(prop, event_value_items); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_value_itemf"); RNA_def_property_ui_text(prop, "Value", ""); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "id", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "id"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "id", "ID of the item"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); 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"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); 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"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); 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"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); 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"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); 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"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "key_modifier", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "keymodifier"); RNA_def_property_enum_items(prop, event_type_items); RNA_def_property_ui_text(prop, "Key Modifier", "Regular key pressed as a modifier"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", KMI_EXPANDED); @@ -1903,15 +1740,21 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_enum_items(prop, keymap_propvalue_items); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_propvalue_itemf"); RNA_def_property_ui_text(prop, "Property Value", "The value this event translates to in a modal keymap"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", KMI_INACTIVE); RNA_def_property_ui_text(prop, "Active", "Activate or deactivate item"); RNA_def_property_ui_icon(prop, ICON_CHECKBOX_DEHLT, 1); + prop= RNA_def_property(srna, "is_user_modified", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", KMI_USER_MODIFIED); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "User Modified", "Is this keymap item modified by the user"); + prop= RNA_def_property(srna, "is_user_defined", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "User Defined", "Is this keymap item user defined (doesn't just override a builtin item)"); + RNA_def_property_ui_text(prop, "User Defined", "Is this keymap item user defined (doesn't just replace a builtin item)"); RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_userdefined_get", NULL); RNA_api_keymapitem(srna); diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index d44b68950f7..89e946f498a 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -84,6 +84,85 @@ void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer) WM_event_remove_timer(wm, timer->win, timer); } +static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) +{ +// wmWindowManager *wm = CTX_wm_manager(C); + char idname_bl[OP_MAX_TYPENAME]; + int modifier= 0; + + /* only on non-modal maps */ + if (km->flag & KEYMAP_MODAL) { + BKE_report(reports, RPT_ERROR, "Not a non-modal keymap."); + return NULL; + } + + WM_operator_bl_idname(idname_bl, idname); + + if(shift) modifier |= KM_SHIFT; + if(ctrl) modifier |= KM_CTRL; + if(alt) modifier |= KM_ALT; + if(oskey) modifier |= KM_OSKEY; + + if(any) modifier = KM_ANY; + + return WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); +} + +static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, ReportList *reports, const char *propvalue_str, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) +{ + int modifier= 0; + int propvalue = 0; + + /* only modal maps */ + if ((km->flag & KEYMAP_MODAL) == 0) { + BKE_report(reports, RPT_ERROR, "Not a modal keymap."); + return NULL; + } + + if (!km->modal_items) { + BKE_report(reports, RPT_ERROR, "No property values defined."); + return NULL; + } + + + if(RNA_enum_value_from_id(km->modal_items, propvalue_str, &propvalue)==0) { + BKE_report(reports, RPT_WARNING, "Property value not in enumeration."); + } + + if(shift) modifier |= KM_SHIFT; + if(ctrl) modifier |= KM_CTRL; + if(alt) modifier |= KM_ALT; + if(oskey) modifier |= KM_OSKEY; + + if(any) modifier = KM_ANY; + + return WM_modalkeymap_add_item(km, type, value, modifier, keymodifier, propvalue); +} + +static wmKeyMap *rna_keymap_new(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid, int modal) +{ + if (modal == 0) { + return WM_keymap_find(keyconf, idname, spaceid, regionid); + } else { + return WM_modalkeymap_add(keyconf, idname, NULL); /* items will be lazy init */ + } +} + +static wmKeyMap *rna_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid) +{ + return WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); +} + +static wmKeyMap *rna_keymap_find_modal(wmKeyConfig *UNUSED(keyconf), const char *idname) +{ + wmOperatorType *ot = WM_operatortype_find(idname, 0); + + if (!ot) + return NULL; + else + return ot->modalkeymap; +} + #else #define WM_GEN_INVOKE_EVENT (1<<0) @@ -301,11 +380,8 @@ void RNA_api_keymap(StructRNA *srna) parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Active key map."); RNA_def_function_return(func, parm); - func= RNA_def_function(srna, "copy_to_user", "WM_keymap_copy_to_user"); - parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "User editable key map."); - RNA_def_function_return(func, parm); - - RNA_def_function(srna, "restore_to_default", "WM_keymap_restore_to_default"); + func= RNA_def_function(srna, "restore_to_default", "WM_keymap_restore_to_default"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); func= RNA_def_function(srna, "restore_item_to_default", "rna_keymap_restore_item_to_default"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -324,5 +400,102 @@ void RNA_api_keymapitem(StructRNA *srna) parm= RNA_def_boolean(func, "result", 0, "Comparison result", ""); RNA_def_function_return(func, parm); } + +void RNA_api_keymapitems(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + func= RNA_def_function(srna, "new", "rna_KeyMap_item_new"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm= RNA_def_string(func, "idname", "", 0, "Operator Identifier", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "type", event_type_items, 0, "Type", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "value", event_value_items, 0, "Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_boolean(func, "any", 0, "Any", ""); + RNA_def_boolean(func, "shift", 0, "Shift", ""); + RNA_def_boolean(func, "ctrl", 0, "Ctrl", ""); + RNA_def_boolean(func, "alt", 0, "Alt", ""); + RNA_def_boolean(func, "oskey", 0, "OS Key", ""); + RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); + parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "new_modal", "rna_KeyMap_item_new_modal"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm= RNA_def_string(func, "propvalue", "", 0, "Property Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "type", event_type_items, 0, "Type", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "value", event_value_items, 0, "Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_boolean(func, "any", 0, "Any", ""); + RNA_def_boolean(func, "shift", 0, "Shift", ""); + RNA_def_boolean(func, "ctrl", 0, "Ctrl", ""); + RNA_def_boolean(func, "alt", 0, "Alt", ""); + RNA_def_boolean(func, "oskey", 0, "OS Key", ""); + RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); + parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove", "WM_keymap_remove_item"); + parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + + func= RNA_def_function(srna, "from_id", "WM_keymap_item_find_id"); + parm= RNA_def_property(func, "id", PROP_INT, PROP_NONE); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_ui_text(parm, "id", "ID of the item"); + parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_function_return(func, parm); +} + +void RNA_api_keymaps(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + func= RNA_def_function(srna, "new", "rna_keymap_new"); // add_keymap + parm= RNA_def_string(func, "name", "", 0, "Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_enum(func, "space_type", space_type_items, SPACE_EMPTY, "Space Type", ""); + RNA_def_enum(func, "region_type", region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); + RNA_def_boolean(func, "modal", 0, "Modal", ""); + parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Added key map."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "find", "rna_keymap_find"); // find_keymap + parm= RNA_def_string(func, "name", "", 0, "Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_enum(func, "space_type", space_type_items, SPACE_EMPTY, "Space Type", ""); + RNA_def_enum(func, "region_type", region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); + parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Corresponding key map."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "find_modal", "rna_keymap_find_modal"); // find_keymap_modal + parm= RNA_def_string(func, "name", "", 0, "Operator Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Corresponding key map."); + RNA_def_function_return(func, parm); +} + +void RNA_api_keyconfigs(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + func= RNA_def_function(srna, "new", "WM_keyconfig_new_user"); // add_keyconfig + parm= RNA_def_string(func, "name", "", 0, "Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Added key configuration."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove", "WM_keyconfig_remove"); // remove_keyconfig + parm= RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Removed key configuration."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} + #endif diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index e6325e2101a..42c3096dfc9 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -41,6 +41,7 @@ /* dna-savable wmStructs here */ #include "DNA_windowmanager_types.h" +#include "WM_keymap.h" #ifdef __cplusplus extern "C" { @@ -114,50 +115,9 @@ void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle); void WM_cursor_warp (struct wmWindow *win, int x, int y); - /* keyconfig and keymap */ -wmKeyConfig *WM_keyconfig_new (struct wmWindowManager *wm, const char *idname); -wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, const char *idname); -void WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf); -void WM_keyconfig_free (struct wmKeyConfig *keyconf); -void WM_keyconfig_userdef(void); - -void WM_keymap_init (struct bContext *C); -void WM_keymap_free (struct wmKeyMap *keymap); - -wmKeyMapItem *WM_keymap_verify_item(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); -wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); -wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); - -void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); -char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len); - -wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid); -wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid); -wmKeyMap *WM_keymap_find_all(const struct bContext *C, const char *idname, int spaceid, int regionid); -wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap); -wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname); -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); -void WM_keymap_properties_reset(struct wmKeyMapItem *kmi, struct IDProperty *properties); -void WM_keymap_restore_item_to_default(struct bContext *C, struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); - -wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id); -int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2); + /* event map */ int WM_userdef_event_map(int kmitype); -wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idname, struct EnumPropertyItem *items); -wmKeyMap *WM_modalkeymap_get(struct wmKeyConfig *keyconf, const char *idname); -wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value); -void WM_modalkeymap_assign(struct wmKeyMap *km, const char *opname); - -const char *WM_key_event_string(short type); -int WM_key_event_operator_id(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, int hotkey, struct wmKeyMap **keymap_r); -char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); - /* handlers */ struct wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap); diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h new file mode 100644 index 00000000000..e00cd288c9a --- /dev/null +++ b/source/blender/windowmanager/WM_keymap.h @@ -0,0 +1,104 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2007 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef WM_KEYMAP_H +#define WM_KEYMAP_H + +/** \file WM_keymap.h + * \ingroup wm + */ + +/* dna-savable wmStructs here */ +#include "DNA_windowmanager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct EnumPropertyItem; + +/* Key Configuration */ + +wmKeyConfig *WM_keyconfig_new (struct wmWindowManager *wm, const char *idname); +wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, const char *idname); +void WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf); +void WM_keyconfig_free (struct wmKeyConfig *keyconf); + +void WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname); + +void WM_keyconfig_update(struct wmWindowManager *wm); +void WM_keyconfig_update_tag(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); + +/* Keymap */ + +void WM_keymap_init (struct bContext *C); +void WM_keymap_free (struct wmKeyMap *keymap); + +wmKeyMapItem *WM_keymap_verify_item(struct wmKeyMap *keymap, const char *idname, int type, + int val, int modifier, int keymodifier); +wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, int type, + int val, int modifier, int keymodifier); +wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type, + int val, int modifier, int keymodifier); + +void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); +char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len); + +wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid); +wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid); +wmKeyMap *WM_keymap_find_all(const struct bContext *C, const char *idname, int spaceid, int regionid); +wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap); +wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname); + +wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id); +int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2); + +/* Modal Keymap */ + +wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idname, struct EnumPropertyItem *items); +wmKeyMap *WM_modalkeymap_get(struct wmKeyConfig *keyconf, const char *idname); +wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value); +void WM_modalkeymap_assign(struct wmKeyMap *km, const char *opname); + +/* Keymap Editor */ + +void WM_keymap_restore_to_default(struct wmKeyMap *keymap, struct bContext *C); +void WM_keymap_properties_reset(struct wmKeyMapItem *kmi, struct IDProperty *properties); +void WM_keymap_restore_item_to_default(struct bContext *C, struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); + +/* Key Event */ + +const char *WM_key_event_string(short type); +int WM_key_event_operator_id(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, int hotkey, struct wmKeyMap **keymap_r); +char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); + +#ifdef __cplusplus +} +#endif + +#endif /* WM_KEYMAP_H */ + diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index a535c0bc1f8..1d5cf1cdc53 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -210,12 +210,18 @@ void WM_keymap_init(bContext *C) if(!wm->defaultconf) wm->defaultconf= WM_keyconfig_new(wm, "Blender"); + if(!wm->addonconf) + wm->addonconf= WM_keyconfig_new(wm, "Blender Addon"); + if(!wm->userconf) + wm->userconf= WM_keyconfig_new(wm, "Blender User"); - if(wm && CTX_py_init_get(C) && (wm->initialized & WM_INIT_KEYMAP) == 0) { + if(CTX_py_init_get(C) && (wm->initialized & WM_INIT_KEYMAP) == 0) { /* create default key config */ wm_window_keymap(wm->defaultconf); ED_spacetypes_keymap(wm->defaultconf); - WM_keyconfig_userdef(); + + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); wm->initialized |= WM_INIT_KEYMAP; } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 2f0c1a72be9..0dac0bd7401 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1735,6 +1735,9 @@ void wm_event_do_handlers(bContext *C) wmWindowManager *wm= CTX_wm_manager(C); wmWindow *win; + /* update key configuration before handling events */ + WM_keyconfig_update(wm); + for(win= wm->windows.first; win; win= win->next) { wmEvent *event; @@ -1938,6 +1941,9 @@ void wm_event_do_handlers(bContext *C) CTX_wm_window_set(C, NULL); } + + /* update key configuration after handling events */ + WM_keyconfig_update(wm); } /* ********** filesector handling ************ */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 27fc0caeccc..20f9d2237c2 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -224,6 +224,14 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) oldwm= oldwmlist->first; wm= G.main->wm.first; + /* move addon key configuration to new wm, to preserve their keymaps */ + if(oldwm->addonconf) { + wm->addonconf= oldwm->addonconf; + BLI_remlink(&oldwm->keyconfigs, oldwm->addonconf); + oldwm->addonconf= NULL; + BLI_addtail(&wm->keyconfigs, wm->addonconf); + } + /* ensure making new keymaps and set space types */ wm->initialized= 0; wm->winactive= NULL; @@ -794,11 +802,14 @@ int WM_write_homefile(bContext *C, wmOperator *op) wmWindow *win= CTX_wm_window(C); char filepath[FILE_MAXDIR+FILE_MAXFILE]; int fileflags; - + /* check current window and close it if temp */ if(win->screen->temp) wm_window_close(C, wm, win); + /* update keymaps in user preferences */ + WM_keyconfig_update(wm); + BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); printf("trying to save homefile at %s ", filepath); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 1720c738dd7..bf48f0e21e4 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -61,14 +61,67 @@ #include "wm_event_system.h" #include "wm_event_types.h" -/* ********************* key config ***********************/ +/******************************* Keymap Item ********************************** + * Item in a keymap, that maps from an event to an operator or modal map item */ -static void keymap_properties_set(wmKeyMapItem *kmi) +static wmKeyMapItem *wm_keymap_item_copy(wmKeyMapItem *kmi) +{ + wmKeyMapItem *kmin = MEM_dupallocN(kmi); + + kmin->prev= kmin->next= NULL; + kmin->flag &= ~KMI_UPDATE; + + if(kmin->properties) { + kmin->ptr= MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr"); + WM_operator_properties_create(kmin->ptr, kmin->idname); + + kmin->properties= IDP_CopyProperty(kmin->properties); + kmin->ptr->data= kmin->properties; + } + + return kmin; +} + +static void wm_keymap_item_free(wmKeyMapItem *kmi) +{ + /* not kmi itself */ + if(kmi->ptr) { + WM_operator_properties_free(kmi->ptr); + MEM_freeN(kmi->ptr); + } +} + +static void wm_keymap_item_properties_set(wmKeyMapItem *kmi) { WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname); WM_operator_properties_sanitize(kmi->ptr, 1); } +static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b) +{ + if(strcmp(a->idname, b->idname) != 0) + return 0; + + if(!((a->ptr==NULL && b->ptr==NULL) || + (a->ptr && b->ptr && IDP_EqualsProperties(a->ptr->data, b->ptr->data)))) + return 0; + + return (a->propvalue == b->propvalue); +} + +static int wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b) +{ + return (wm_keymap_item_equals_result(a, b) && + a->type == b->type && + a->val == b->val && + a->shift == b->shift && + a->ctrl == b->ctrl && + a->alt == b->alt && + a->oskey == b->oskey && + a->keymodifier == b->keymodifier && + a->maptype == b->maptype); +} + /* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */ void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties) { @@ -78,9 +131,41 @@ void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties kmi->ptr = NULL; kmi->properties = properties; - keymap_properties_set(kmi); + wm_keymap_item_properties_set(kmi); +} + +/**************************** Keymap Diff Item ********************************* + * Item in a diff keymap, used for saving diff of keymaps in user preferences */ + +static wmKeyMapDiffItem *wm_keymap_diff_item_copy(wmKeyMapDiffItem *kmdi) +{ + wmKeyMapDiffItem *kmdin = MEM_dupallocN(kmdi); + + kmdin->next = kmdin->prev = NULL; + if(kmdi->add_item) + kmdin->add_item = wm_keymap_item_copy(kmdi->add_item); + if(kmdi->remove_item) + kmdin->remove_item = wm_keymap_item_copy(kmdi->remove_item); + + return kmdin; +} + +static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi) +{ + if(kmdi->remove_item) { + wm_keymap_item_free(kmdi->remove_item); + MEM_freeN(kmdi->remove_item); + } + if(kmdi->add_item) { + wm_keymap_item_free(kmdi->add_item); + MEM_freeN(kmdi->add_item); + } } +/***************************** Key Configuration ****************************** + * List of keymaps for all editors, modes, ... . There is a builtin default key + * configuration, a user key configuration, and other preset configurations. */ + wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname) { wmKeyConfig *keyconf; @@ -106,6 +191,7 @@ void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) if (keyconf) { if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) { BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr)); + WM_keyconfig_update_tag(NULL, NULL); } BLI_remlink(&wm->keyconfigs, keyconf); @@ -125,21 +211,6 @@ void WM_keyconfig_free(wmKeyConfig *keyconf) MEM_freeN(keyconf); } -void WM_keyconfig_userdef(void) -{ - wmKeyMap *km; - wmKeyMapItem *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) { wmKeyConfig *kc; @@ -151,23 +222,84 @@ static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname) return NULL; } -/* ************************ free ************************* */ +wmKeyConfig *WM_keyconfig_active(wmWindowManager *wm) +{ + wmKeyConfig *keyconf; -void WM_keymap_free(wmKeyMap *keymap) + /* first try from preset */ + keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr); + if(keyconf) + return keyconf; + + /* otherwise use default */ + return wm->defaultconf; +} + +void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname) { - wmKeyMapItem *kmi; + /* setting a different key configuration as active: we ensure all is + updated properly before and after making the change */ + + WM_keyconfig_update(wm); + + BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr)); + + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); +} + +/********************************** Keymap ************************************* + * List of keymap items for one editor, mode, modal operator, ... */ + +static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid) +{ + wmKeyMap *km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list"); + + BLI_strncpy(km->idname, idname, KMAP_MAX_NAME); + km->spaceid= spaceid; + km->regionid= regionid; + + return km; +} + +static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap) +{ + wmKeyMap *keymapn = MEM_dupallocN(keymap); + wmKeyMapItem *kmi, *kmin; + wmKeyMapDiffItem *kmdi, *kmdin; + + keymapn->modal_items= keymap->modal_items; + keymapn->poll= keymap->poll; + keymapn->items.first= keymapn->items.last= NULL; + keymapn->flag &= ~(KEYMAP_UPDATE|KEYMAP_EXPANDED); + + for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) { + kmdin= wm_keymap_diff_item_copy(kmdi); + BLI_addtail(&keymapn->items, kmdin); + } for(kmi=keymap->items.first; kmi; kmi=kmi->next) { - if(kmi->ptr) { - WM_operator_properties_free(kmi->ptr); - MEM_freeN(kmi->ptr); - } + kmin= wm_keymap_item_copy(kmi); + BLI_addtail(&keymapn->items, kmin); } - BLI_freelistN(&keymap->items); + return keymapn; } -/* ***************** generic call, exported **************** */ +void WM_keymap_free(wmKeyMap *keymap) +{ + wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; + + for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) + wm_keymap_diff_item_free(kmdi); + + for(kmi=keymap->items.first; kmi; kmi=kmi->next) + wm_keymap_item_free(kmi); + + BLI_freelistN(&keymap->diff_items); + BLI_freelistN(&keymap->items); +} static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier) { @@ -229,7 +361,7 @@ wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int ty keymap_item_set_id(keymap, kmi); keymap_event_set(kmi, type, val, modifier, keymodifier); - keymap_properties_set(kmi); + wm_keymap_item_properties_set(kmi); } return kmi; } @@ -243,10 +375,12 @@ wmKeyMapItem *WM_keymap_add_item(wmKeyMap *keymap, const char *idname, int type, BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME); keymap_event_set(kmi, type, val, modifier, keymodifier); - keymap_properties_set(kmi); + wm_keymap_item_properties_set(kmi); keymap_item_set_id(keymap, kmi); + WM_keyconfig_update_tag(keymap, kmi); + return kmi; } @@ -266,6 +400,232 @@ void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) MEM_freeN(kmi->ptr); } BLI_freelinkN(&keymap->items, kmi); + + WM_keyconfig_update_tag(keymap, kmi); + } +} + +/************************** Keymap Diff and Patch **************************** + * Rather than saving the entire keymap for user preferences, we only save a + * diff so that changes in the defaults get synced. This system is not perfect + * but works better than overriding the keymap entirely when only few items + * are changed. */ + +static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap) +{ + wmKeyMapItem *kmi, *kmin; + + for(kmi=addonmap->items.first; kmi; kmi=kmi->next) { + kmin = wm_keymap_item_copy(kmi); + keymap_item_set_id(keymap, kmin); + BLI_addhead(&keymap->items, kmin); + } +} + +static wmKeyMapItem *wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *needle) +{ + wmKeyMapItem *kmi; + + for(kmi=km->items.first; kmi; kmi=kmi->next) + if(wm_keymap_item_equals(kmi, needle)) + return kmi; + + return NULL; +} + +static wmKeyMapItem *wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapItem *needle) +{ + wmKeyMapItem *kmi; + + for(kmi=km->items.first; kmi; kmi=kmi->next) + if(wm_keymap_item_equals_result(kmi, needle)) + return kmi; + + return NULL; +} + +static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km) +{ + wmKeyMapItem *kmi, *to_kmi, *orig_kmi; + wmKeyMapDiffItem *kmdi; + + for(kmi=from_km->items.first; kmi; kmi=kmi->next) { + to_kmi = WM_keymap_item_find_id(to_km, kmi->id); + + if(!to_kmi) { + /* remove item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->remove_item = wm_keymap_item_copy(kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + else if(to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) { + /* replace item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->remove_item = wm_keymap_item_copy(kmi); + kmdi->add_item = wm_keymap_item_copy(to_kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + + /* sync expanded flag back to original so we don't loose it on repatch */ + if(to_kmi) { + orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id); + + if(!orig_kmi) + orig_kmi = wm_keymap_find_item_equals(addon_km, kmi); + + if(orig_kmi) { + orig_kmi->flag &= ~KMI_EXPANDED; + orig_kmi->flag |= (to_kmi->flag & KMI_EXPANDED); + } + } + } + + for(kmi=to_km->items.first; kmi; kmi=kmi->next) { + if(kmi->id < 0) { + /* add item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->add_item = wm_keymap_item_copy(kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + } +} + +static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km) +{ + wmKeyMapDiffItem *kmdi; + wmKeyMapItem *kmi_remove, *kmi_add; + + for(kmdi=diff_km->diff_items.first; kmdi; kmdi=kmdi->next) { + /* find item to remove */ + kmi_remove = NULL; + if(kmdi->remove_item) { + kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item); + if(!kmi_remove) + kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item); + } + + /* add item */ + if(kmdi->add_item) { + /* only if nothing to remove or item to remove found */ + if(!kmdi->remove_item || kmi_remove) { + kmi_add = wm_keymap_item_copy(kmdi->add_item); + kmi_add->flag |= KMI_USER_MODIFIED; + + if(kmi_remove) { + kmi_add->flag &= ~KMI_EXPANDED; + kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED); + kmi_add->id = kmi_remove->id; + BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add); + } + else { + keymap_item_set_id(km, kmi_add); + BLI_addtail(&km->items, kmi_add); + } + } + } + + /* remove item */ + if(kmi_remove) { + wm_keymap_item_free(kmi_remove); + BLI_freelinkN(&km->items, kmi_remove); + } + } +} + +static void wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap) +{ + wmKeyMap *km; + int expanded = 0; + + /* remove previous keymap in list, we will replace it */ + km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid); + if(km) { + expanded = (km->flag & (KEYMAP_EXPANDED|KEYMAP_CHILDREN_EXPANDED)); + WM_keymap_free(km); + BLI_freelinkN(lb, km); + } + + /* copy new keymap from an existing one */ + if(usermap && !(usermap->flag & KEYMAP_DIFF)) { + /* for compatibiltiy with old user preferences with non-diff + keymaps we override the original entirely */ + wmKeyMapItem *kmi, *orig_kmi; + + km = wm_keymap_copy(usermap); + km->modal_items = defaultmap->modal_items; + km->poll = defaultmap->poll; + + /* try to find corresponding id's for items */ + for(kmi=km->items.first; kmi; kmi=kmi->next) { + orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi); + if(!orig_kmi) + orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi); + + if(orig_kmi) + kmi->id = orig_kmi->id; + else + kmi->id = -(km->kmi_id++); + } + + km->flag |= KEYMAP_UPDATE; /* update again to create diff */ + } + else + km = wm_keymap_copy(defaultmap); + + /* add addon keymap items */ + if(addonmap) + wm_keymap_addon_add(km, addonmap); + + /* tag as being user edited */ + if(usermap) + km->flag |= KEYMAP_USER_MODIFIED; + km->flag |= KEYMAP_USER|expanded; + + /* apply user changes of diff keymap */ + if(usermap && (usermap->flag & KEYMAP_DIFF)) + wm_keymap_patch(km, usermap); + + /* add to list */ + BLI_addtail(lb, km); +} + +static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *km) +{ + wmKeyMap *diffmap, *prevmap, *origmap; + + /* create temporary default + addon keymap for diff */ + origmap = defaultmap; + + if(addonmap) { + defaultmap = wm_keymap_copy(defaultmap); + wm_keymap_addon_add(defaultmap, addonmap); + } + + /* remove previous diff keymap in list, we will replace it */ + prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid); + if(prevmap) { + WM_keymap_free(prevmap); + BLI_freelinkN(lb, prevmap); + } + + /* create diff keymap */ + diffmap= wm_keymap_new(km->idname, km->spaceid, km->regionid); + diffmap->flag |= KEYMAP_DIFF; + wm_keymap_diff(diffmap, defaultmap, km, origmap, addonmap); + + /* add to list if not empty */ + if(diffmap->diff_items.first) { + BLI_addtail(lb, diffmap); + } + else { + WM_keymap_free(diffmap); + MEM_freeN(diffmap); + } + + /* free temporary default map */ + if(addonmap) { + WM_keymap_free(defaultmap); + MEM_freeN(defaultmap); } } @@ -292,11 +652,10 @@ wmKeyMap *WM_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, wmKeyMap *km= WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); if(km==NULL) { - km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list"); - BLI_strncpy(km->idname, idname, KMAP_MAX_NAME); - km->spaceid= spaceid; - km->regionid= regionid; + km= wm_keymap_new(idname, spaceid, regionid); BLI_addtail(&keyconf->keymaps, km); + + WM_keyconfig_update_tag(km, NULL); } return km; @@ -304,29 +663,9 @@ wmKeyMap *WM_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, wmKeyMap *WM_keymap_find_all(const bContext *C, const char *idname, int spaceid, int regionid) { - wmWindowManager *wm = CTX_wm_manager(C); - wmKeyConfig *keyconf; - wmKeyMap *km; - - /* first user defined keymaps */ - km= WM_keymap_list_find(&U.keymaps, idname, spaceid, regionid); - if (km) - return km; - - /* then user key config */ - keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr); - if(keyconf) { - km= WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); - if (km) - return km; - } - - /* then use default */ - km= WM_keymap_list_find(&wm->defaultconf->keymaps, idname, spaceid, regionid); - if (km) - return km; - else - return NULL; + wmWindowManager *wm= CTX_wm_manager(C); + + return WM_keymap_list_find(&wm->userconf->keymaps, idname, spaceid, regionid); } /* ****************** modal keymaps ************ */ @@ -366,6 +705,8 @@ wmKeyMapItem *WM_modalkeymap_add_item(wmKeyMap *km, int type, int val, int modif keymap_item_set_id(km, kmi); + WM_keyconfig_update_tag(km, kmi); + return kmi; } @@ -588,169 +929,209 @@ int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) return 1; } -/* ***************** user preferences ******************* */ +/************************* Update Final Configuration ************************* + * On load or other changes, the final user key configuration is rebuilt from + * the preset, addon and user preferences keymaps. We also test if the final + * configuration changed and write the changes to the user preferences. */ + +static int WM_KEYMAP_UPDATE = 0; -int WM_keymap_user_init(wmWindowManager *wm, wmKeyMap *keymap) +void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi) { - wmKeyConfig *keyconf; - wmKeyMap *km; + /* quick tag to do delayed keymap updates */ + WM_KEYMAP_UPDATE= 1; - if(!keymap) - return 0; + if(km) + km->flag |= KEYMAP_UPDATE; + if(kmi) + kmi->flag |= KMI_UPDATE; +} - /* 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; - } - } +static int wm_keymap_test_and_clear_update(wmKeyMap *km) +{ + wmKeyMapItem *kmi; + int update; + + update= (km->flag & KEYMAP_UPDATE); + km->flag &= ~KEYMAP_UPDATE; - /* 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; + for(kmi=km->items.first; kmi; kmi=kmi->next) { + update= update || (kmi->flag & KMI_UPDATE); + kmi->flag &= ~KMI_UPDATE; } - - return 0; + + return update; } -wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) +static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km) { - wmKeyConfig *keyconf; - wmKeyMap *km; + wmKeyConfig *keyconf= WM_keyconfig_active(wm); + wmKeyMap *keymap; + keymap= WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid); if(!keymap) - return NULL; - - /* first user defined keymaps */ - 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; - } - - /* then 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) { - km->poll= keymap->poll; /* lazy init */ - km->modal_items= keymap->modal_items; - return km; - } - } + keymap= WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid); - /* then use default */ - km= WM_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - return km; + return keymap; } -wmKeyMap *WM_keymap_copy_to_user(wmKeyMap *keymap) +void WM_keyconfig_update(wmWindowManager *wm) { - wmKeyMap *usermap; + wmKeyMap *km, *defaultmap, *addonmap, *usermap; wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; + int compat_update = 0; - usermap= WM_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - - /* XXX this function is only used by RMB setting hotkeys, and it clears maps on 2nd try this way */ - if(keymap==usermap) - return keymap; + if(!WM_KEYMAP_UPDATE) + return; - if(!usermap) { - /* not saved yet, duplicate existing */ - usermap= MEM_dupallocN(keymap); - usermap->modal_items= NULL; - usermap->poll= NULL; - usermap->flag |= KEYMAP_USER; + /* update operator properties for non-modal user keymaps */ + for(km=U.user_keymaps.first; km; km=km->next) { + if((km->flag & KEYMAP_MODAL) == 0) { + for(kmdi=km->diff_items.first; kmdi; kmdi=kmdi->next) { + if(kmdi->add_item) + wm_keymap_item_properties_set(kmdi->add_item); + if(kmdi->remove_item) + wm_keymap_item_properties_set(kmdi->remove_item); + } - BLI_addtail(&U.keymaps, usermap); + for(kmi=km->items.first; kmi; kmi=kmi->next) + wm_keymap_item_properties_set(kmi); + } } - else { - /* already saved, free items for re-copy */ - WM_keymap_free(usermap); + + /* update U.user_keymaps with user key configuration changes */ + for(km=wm->userconf->keymaps.first; km; km=km->next) { + /* only diff if the user keymap was modified */ + if(wm_keymap_test_and_clear_update(km)) { + /* find keymaps */ + defaultmap= wm_keymap_preset(wm, km); + addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); + + /* diff */ + wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km); + } } - BLI_duplicatelist(&usermap->items, &keymap->items); + /* create user key configuration from preset + addon + user preferences */ + for(km=wm->defaultconf->keymaps.first; km; km=km->next) { + /* find keymaps */ + defaultmap= wm_keymap_preset(wm, km); + addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); + usermap= WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid); - for(kmi=usermap->items.first; kmi; kmi=kmi->next) { - if(kmi->properties) { - kmi->ptr= MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr"); - WM_operator_properties_create(kmi->ptr, kmi->idname); + /* add */ + wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap); - kmi->properties= IDP_CopyProperty(kmi->properties); - kmi->ptr->data= kmi->properties; - } + /* in case of old non-diff keymaps, force extra update to create diffs */ + compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF)); } - for(kmi=keymap->items.first; kmi; kmi=kmi->next) - kmi->flag &= ~KMI_EXPANDED; + WM_KEYMAP_UPDATE= 0; + + if(compat_update) { + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); + } +} + +/********************************* Event Handling ***************************** + * Handlers have pointers to the keymap in the default configuration. During + * event handling this function is called to get the keymap from the final + * configuration. */ + +wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) +{ + wmKeyMap *km; + + if(!keymap) + return NULL; + + /* first user defined keymaps */ + km= WM_keymap_list_find(&wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + + if(km) + return km; - return usermap; + return keymap; } +/******************************* Keymap Editor ******************************** + * In the keymap editor the user key configuration is edited. */ + void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi) { wmWindowManager *wm = CTX_wm_manager(C); - wmKeyConfig *keyconf; - wmKeyMap *km = NULL; + wmKeyMap *defaultmap, *addonmap; + wmKeyMapItem *orig; - /* look in 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(!keymap) + return; + + /* construct default keymap from preset + addons */ + defaultmap= wm_keymap_preset(wm, keymap); + addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - if (!km) { - /* or from default */ - km= WM_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + if(addonmap) { + defaultmap = wm_keymap_copy(defaultmap); + wm_keymap_addon_add(defaultmap, addonmap); } - if (km) { - wmKeyMapItem *orig = WM_keymap_item_find_id(km, kmi->id); + /* find original item */ + orig = WM_keymap_item_find_id(defaultmap, kmi->id); - if (orig) { - if(strcmp(orig->idname, kmi->idname) != 0) { - BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname)); + if(orig) { + /* restore to original */ + if(strcmp(orig->idname, kmi->idname) != 0) { + BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname)); + WM_keymap_properties_reset(kmi, NULL); + } - WM_keymap_properties_reset(kmi, NULL); - } - - if (orig->properties) { - kmi->properties= IDP_CopyProperty(orig->properties); - kmi->ptr->data= kmi->properties; + if (orig->properties) { + if(kmi->properties) { + IDP_FreeProperty(kmi->properties); + MEM_freeN(kmi->properties); + kmi->properties= NULL; } - kmi->propvalue = orig->propvalue; - kmi->type = orig->type; - kmi->val = orig->val; - kmi->shift = orig->shift; - kmi->ctrl = orig->ctrl; - kmi->alt = orig->alt; - kmi->oskey = orig->oskey; - kmi->keymodifier = orig->keymodifier; - kmi->maptype = orig->maptype; - + kmi->properties= IDP_CopyProperty(orig->properties); + kmi->ptr->data= kmi->properties; } + kmi->propvalue = orig->propvalue; + kmi->type = orig->type; + kmi->val = orig->val; + kmi->shift = orig->shift; + kmi->ctrl = orig->ctrl; + kmi->alt = orig->alt; + kmi->oskey = orig->oskey; + kmi->keymodifier = orig->keymodifier; + kmi->maptype = orig->maptype; + + WM_keyconfig_update_tag(keymap, kmi); + } + + /* free temporary keymap */ + if(addonmap) { + WM_keymap_free(defaultmap); + MEM_freeN(defaultmap); } } -void WM_keymap_restore_to_default(wmKeyMap *keymap) +void WM_keymap_restore_to_default(wmKeyMap *keymap, bContext *C) { + wmWindowManager *wm = CTX_wm_manager(C); wmKeyMap *usermap; - usermap= WM_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + /* remove keymap from U.user_keymaps and update */ + usermap= WM_keymap_list_find(&U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid); if(usermap) { WM_keymap_free(usermap); - BLI_freelinkN(&U.keymaps, usermap); + BLI_freelinkN(&U.user_keymaps, usermap); + + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); } } @@ -951,3 +1332,4 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) return km; } + diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 548d272ffd2..983d4ecf5f8 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -208,10 +208,12 @@ struct wmKeyMap *WM_keymap_list_find(struct ListBase *lb, char *idname, int spac struct wmKeyConfig *WM_keyconfig_new(struct wmWindowManager *wm, char *idname){return (struct wmKeyConfig *) NULL;} struct wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, char *idname){return (struct wmKeyConfig *) NULL;} void WM_keyconfig_remove(struct wmWindowManager *wm, char *idname){} +void WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname) {} void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi){} void WM_keymap_restore_to_default(struct wmKeyMap *keymap){} void WM_keymap_restore_item_to_default(struct bContext *C, struct wmKeyMap *keymap, struct wmKeyMapItem *kmi){} void WM_keymap_properties_reset(struct wmKeyMapItem *kmi){} +void WM_keyconfig_update_tag(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi) {} int WM_keymap_user_init(struct wmWindowManager *wm, struct wmKeyMap *keymap) {return 0;} int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2){return 0;} |