diff options
-rw-r--r-- | source/blender/blenkernel/BKE_idprop.h | 11 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/idprop.c | 15 | ||||
-rw-r--r-- | source/blender/python/generic/idprop_py_api.c | 37 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_keymap.c | 57 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 36 |
6 files changed, 139 insertions, 18 deletions
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 027f06ef84f..2dd1bfc2a51 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -266,6 +266,12 @@ __attribute__((nonnull)) #endif ; +int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_strict) +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +; + int IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) #ifdef __GNUC__ __attribute__((warn_unused_result)) @@ -319,4 +325,9 @@ void IDP_UnlinkProperty(struct IDProperty *prop); #define IDP_IDPArray(prop) ((IDProperty *)(prop)->data.pointer) #define IDP_Double(prop) (*(double *)&(prop)->data.val) +#ifdef DEBUG +/* for printout only */ +void IDP_spit(IDProperty *prop); +#endif + #endif /* __BKE_IDPROP_H__ */ diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 584de4cd982..5dd0f08dc71 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -632,12 +632,14 @@ IDProperty *IDP_GetProperties(ID *id, int create_if_needed) } } -int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) +/** + * \param is_strict When FALSE treat missing items as a match */ +int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_strict) { if (prop1 == NULL && prop2 == NULL) return 1; else if (prop1 == NULL || prop2 == NULL) - return 0; + return is_strict ? 0 : 1; else if (prop1->type != prop2->type) return 0; @@ -661,13 +663,13 @@ int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) { IDProperty *link1, *link2; - if (BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group)) + if (is_strict && BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group)) return 0; for (link1 = prop1->data.group.first; link1; link1 = link1->next) { link2 = IDP_GetPropertyFromGroup(prop2, link1->name); - if (!IDP_EqualsProperties(link1, link2)) + if (!IDP_EqualsProperties_ex(link1, link2, is_strict)) return 0; } @@ -696,6 +698,11 @@ int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) return 1; } +int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) +{ + return IDP_EqualsProperties_ex(prop1, prop2, TRUE); +} + /* 'val' is never NULL, don't check */ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) { diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 05b37514e20..34210ace884 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -1497,3 +1497,40 @@ PyObject *BPyInit_idprop(void) return mod; } + + +#ifdef DEBUG +/* -------------------------------------------------------------------- */ +/* debug only function */ + +void IDP_spit(IDProperty *prop) +{ + if (prop) { + PyGILState_STATE gilstate; + int use_gil = TRUE; /* !PYC_INTERPRETER_ACTIVE; */ + PyObject *ret_dict; + PyObject *ret_str; + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + /* to_dict() */ + ret_dict = BPy_IDGroup_MapDataToPy(prop); + ret_str = PyObject_Repr(ret_dict); + Py_DECREF(ret_dict); + + printf("IDProperty: %s\n", _PyUnicode_AsString(ret_str)); + + Py_DECREF(ret_str); + + if (use_gil) { + PyGILState_Release(gilstate); + } + } + else { + printf("IDProperty: <NIL>\n"); + } +} + +#endif diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 04e8b65a2ef..b9a4e720230 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -214,6 +214,7 @@ int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short c void WM_operator_properties_alloc(struct PointerRNA **ptr, struct IDProperty **properties, const char *opstring); /* used for keymap and macro items */ void WM_operator_properties_sanitize(struct PointerRNA *ptr, const short no_context); /* make props context sensitive or not */ +int WM_operator_properties_default(struct PointerRNA *ptr, const int do_update); void WM_operator_properties_reset(struct wmOperator *op); void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring); void WM_operator_properties_create_ptr(struct PointerRNA *ptr, struct wmOperatorType *ot); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index bcddc984ed3..2781ec2d3df 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -816,7 +816,7 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len) static wmKeyMapItem *wm_keymap_item_find_handlers( const bContext *C, ListBase *handlers, const char *opname, int UNUSED(opcontext), - IDProperty *properties, int compare_props, int hotkey, wmKeyMap **keymap_r) + IDProperty *properties, int is_strict, int hotkey, wmKeyMap **keymap_r) { wmWindowManager *wm = CTX_wm_manager(C); wmEventHandler *handler; @@ -834,9 +834,22 @@ static wmKeyMapItem *wm_keymap_item_find_handlers( if (hotkey) if (!ISHOTKEY(kmi->type)) continue; - - if (compare_props) { - if (kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) { + + if (properties) { + + /* example of debugging keymaps */ +#if 0 + if (kmi->ptr) { + if (strcmp("MESH_OT_rip_move", opname) == 0) { + printf("OPERATOR\n"); + IDP_spit(properties); + printf("KEYMAP\n"); + IDP_spit(kmi->ptr->data); + } + } +#endif + + if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) { if (keymap_r) *keymap_r = keymap; return kmi; } @@ -857,7 +870,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers( static wmKeyMapItem *wm_keymap_item_find_props( const bContext *C, const char *opname, int opcontext, - IDProperty *properties, int compare_props, int hotkey, wmKeyMap **keymap_r) + IDProperty *properties, int is_strict, int hotkey, wmKeyMap **keymap_r) { wmWindow *win = CTX_wm_window(C); ScrArea *sa = CTX_wm_area(C); @@ -866,10 +879,10 @@ static wmKeyMapItem *wm_keymap_item_find_props( /* look into multiple handler lists to find the item */ if (win) - found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); if (sa && found == NULL) - found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); if (found == NULL) { if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { @@ -878,7 +891,7 @@ static wmKeyMapItem *wm_keymap_item_find_props( ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); } } else if (ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) { @@ -886,18 +899,18 @@ static wmKeyMapItem *wm_keymap_item_find_props( ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); } else if (ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) { if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW)) ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); } else { if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); } } @@ -906,12 +919,28 @@ static wmKeyMapItem *wm_keymap_item_find_props( static wmKeyMapItem *wm_keymap_item_find( const bContext *C, const char *opname, int opcontext, - IDProperty *properties, const short hotkey, const short sloppy, wmKeyMap **keymap_r) + IDProperty *properties, const short hotkey, const short UNUSED(sloppy), wmKeyMap **keymap_r) { wmKeyMapItem *found = wm_keymap_item_find_props(C, opname, opcontext, properties, 1, hotkey, keymap_r); - if (!found && sloppy) - found = wm_keymap_item_find_props(C, opname, opcontext, NULL, 0, hotkey, keymap_r); + if (!found && properties) { + wmOperatorType *ot = WM_operatortype_find(opname, TRUE); + if (ot) { + /* make a copy of the properties and set any unset props + * to their default values, so the ID property compare function succeeds */ + PointerRNA opptr; + IDProperty *properties_default = IDP_CopyProperty(properties); + + RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); + + if (WM_operator_properties_default(&opptr, TRUE)) { + found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, 0, hotkey, keymap_r); + } + + IDP_FreeProperty(properties_default); + MEM_freeN(properties_default); + } + } return found; } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 8d01cdb694d..2ef33aa5964 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -619,6 +619,42 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context) RNA_STRUCT_END; } + +/** set all props to their default, + * \param do_update Only update un-initialized props. + * + * \note, theres nothing spesific to operators here. + * this could be made a general function. + */ +int WM_operator_properties_default(PointerRNA *ptr, const int do_update) +{ + int is_change = FALSE; + RNA_STRUCT_BEGIN(ptr, prop) + { + switch (RNA_property_type(prop)) { + case PROP_POINTER: + { + StructRNA *ptype = RNA_property_pointer_type(ptr, prop); + if (ptype != &RNA_Struct) { + PointerRNA opptr = RNA_property_pointer_get(ptr, prop); + is_change |= WM_operator_properties_default(&opptr, do_update); + } + break; + } + default: + if ((do_update == FALSE) || (RNA_property_is_set(ptr, prop) == FALSE)) { + if (RNA_property_reset(ptr, prop, -1)) { + is_change = 1; + } + } + break; + } + } + RNA_STRUCT_END; + + return is_change; +} + /* remove all props without PROP_SKIP_SAVE */ void WM_operator_properties_reset(wmOperator *op) { |