diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/object/object_edit.c | 5 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_edit.c | 5 | ||||
-rw-r--r-- | source/blender/editors/space_node/space_node.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_sequencer/sequencer_view.c | 11 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/space_view3d.c | 25 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_wm.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 12 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 11 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm.c | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 59 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 6 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_widgets.c | 276 | ||||
-rw-r--r-- | source/blender/windowmanager/wm.h | 9 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_system.h | 4 |
14 files changed, 379 insertions, 53 deletions
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 05a55a8996b..6913710b9f9 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -2101,8 +2101,9 @@ static int object_widget_add_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = ED_object_active_context((bContext *)C); wmWidgetGroupType *wgrouptype = WM_widgetgrouptype_new(WIDGETGROUP_object_manipulator_poll, WIDGETGROUP_object_manipulator_create, - CTX_data_main(C), "View3D", SPACE_VIEW3D, - RGN_TYPE_WINDOW, true); + WM_widgetgroup_keymap_common, + CTX_data_main(C), "View3D", "Object Widgets", + SPACE_VIEW3D, RGN_TYPE_WINDOW, true); /* assign the objects id name to the widget */ strcpy(wgrouptype->idname, ob->id.name); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 0d43efdbb21..ca962d2147a 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -2540,7 +2540,10 @@ static int graph_widget_backdrop_transform_invoke(bContext *C, wmOperator *op, c ScrArea *sa = CTX_wm_area(C); SpaceIpo *sipo = CTX_wm_space_graph(C); /* no poll, lives always for the duration of the operator */ - wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_backdrop_create, CTX_data_main(C), "Graph_Canvas", SPACE_IPO, RGN_TYPE_WINDOW, false); + wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_backdrop_create, + WM_widgetgroup_keymap_common, CTX_data_main(C), + "Graph_Canvas", "Backdrop Transform Widgets", + SPACE_IPO, RGN_TYPE_WINDOW, false); struct wmEventHandler *handler = WM_event_add_modal_handler(C, op); BackDropTransformData *data = MEM_mallocN(sizeof(BackDropTransformData), "overdrop transform data"); WM_modal_handler_attach_widgetgroup(C, handler, cagetype, op); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 29e513fe65c..08231da5993 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -888,7 +888,11 @@ static void node_widgets(void) /* create the widgetmap for the area here */ WM_widgetmaptype_find("Node_Canvas", SPACE_NODE, RGN_TYPE_WINDOW, false, true); - WM_widgetgrouptype_new(WIDGETGROUP_node_transform_poll, WIDGETGROUP_node_transform_create, NULL, "Node_Canvas", SPACE_NODE, RGN_TYPE_WINDOW, false); + WM_widgetgrouptype_new(WIDGETGROUP_node_transform_poll, + WIDGETGROUP_node_transform_create, + WM_widgetgroup_keymap_common, + NULL, "Node_Canvas", "Backdrop Transform Widgets", + SPACE_NODE, RGN_TYPE_WINDOW, false); } /* only called once, from space/spacetypes.c */ diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index ebe0a389a2c..3208a115b18 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -293,7 +293,10 @@ static int sequencer_overdrop_transform_invoke(bContext *C, wmOperator *op, cons ScrArea *sa = CTX_wm_area(C); SpaceSeq *sseq = CTX_wm_space_seq(C); /* no poll, lives always for the duration of the operator */ - wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_overdrop_create, CTX_data_main(C), "Seq_Canvas", SPACE_SEQ, RGN_TYPE_WINDOW, false); + wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_overdrop_create, + WM_widgetgroup_keymap_common, CTX_data_main(C), + "Seq_Canvas", "Backdrop Transform Widgets", + SPACE_SEQ, RGN_TYPE_WINDOW, false); struct wmEventHandler *handler = WM_event_add_modal_handler(C, op); OverDropTransformData *data = MEM_mallocN(sizeof(OverDropTransformData), "overdrop transform data"); WM_modal_handler_attach_widgetgroup(C, handler, cagetype, op); @@ -457,8 +460,10 @@ static int sequencer_image_transform_widget_invoke(bContext *C, wmOperator *op, SpaceSeq *sseq = CTX_wm_space_seq(C); Scene *scene = CTX_data_scene(C); /* no poll, lives always for the duration of the operator */ - wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_image_transform_create, CTX_data_main(C), - "Seq_Canvas", SPACE_SEQ, RGN_TYPE_PREVIEW, false); + wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_image_transform_create, + WM_widgetgroup_keymap_common, CTX_data_main(C), + "Seq_Canvas", "Image Transform Widgets", + SPACE_SEQ, RGN_TYPE_PREVIEW, false); struct wmEventHandler *handler = WM_event_add_modal_handler(C, op); ImageTransformData *data = MEM_mallocN(sizeof(ImageTransformData), "overdrop transform data"); ImBuf *ibuf = sequencer_ibuf_get(CTX_data_main(C), scene, sseq, CFRA, 0, NULL); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index c42c04639c3..1b46040adc1 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -976,11 +976,26 @@ static void view3d_widgets(void) { WM_widgetmaptype_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true, true); - WM_widgetgrouptype_new(WIDGETGROUP_armature_facemap_poll, WIDGETGROUP_armature_facemap_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); - WM_widgetgrouptype_new(WIDGETGROUP_lamp_poll, WIDGETGROUP_lamp_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); - WM_widgetgrouptype_new(WIDGETGROUP_forcefield_poll, WIDGETGROUP_forcefield_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); - WM_widgetgrouptype_new(WIDGETGROUP_camera_poll, WIDGETGROUP_camera_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); - WM_widgetgrouptype_new(WIDGETGROUP_manipulator_poll, WIDGETGROUP_manipulator_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); + WM_widgetgrouptype_new(WIDGETGROUP_armature_facemap_poll, + WIDGETGROUP_armature_facemap_create, + WM_widgetgroup_keymap_common, + NULL, "View3D", "Face Map Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); + WM_widgetgrouptype_new(WIDGETGROUP_lamp_poll, + WIDGETGROUP_lamp_create, + WM_widgetgroup_keymap_common, + NULL, "View3D", "Lamp Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); + WM_widgetgrouptype_new(WIDGETGROUP_forcefield_poll, + WIDGETGROUP_forcefield_create, + WM_widgetgroup_keymap_common, + NULL, "View3D", "Force Field Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); + WM_widgetgrouptype_new(WIDGETGROUP_camera_poll, + WIDGETGROUP_camera_create, + WM_widgetgroup_keymap_common, + NULL, "View3D", "Camera Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); + WM_widgetgrouptype_new(WIDGETGROUP_manipulator_poll, + WIDGETGROUP_manipulator_create, + WM_widgetgroup_keymap_common, + NULL, "View3D", "Manipulator Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true); } diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index c982c139a53..c597a3cc7e5 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1568,7 +1568,7 @@ static StructRNA *rna_WidgetGroup_register(Main *bmain, ReportList *reports, voi dummywgt.poll = (have_function[0]) ? widgetgroup_poll : NULL; dummywgt.create = (have_function[1]) ? widgetgroup_draw : NULL; - wgrouptype = WM_widgetgrouptype_new(dummywgt.poll, dummywgt.create, bmain, dummywgt.mapidname, dummywgt.spaceid, dummywgt.regionid, dummywgt.is_3d); + wgrouptype = WM_widgetgrouptype_new(dummywgt.poll, dummywgt.create, NULL, bmain, dummywgt.mapidname, NULL, dummywgt.spaceid, dummywgt.regionid, dummywgt.is_3d); memcpy(wgrouptype, &dummywgt, sizeof(dummywgt)); /* update while blender is running */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 51aacb61a55..1e5e09bb9e4 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -536,12 +536,16 @@ void WM_widget_set_scale(struct wmWidget *widget, float scale); void WM_widget_set_line_width(struct wmWidget *widget, const float line_width); void WM_widget_set_colors(struct wmWidget *widget, const float col[4], const float col_hi[4]); +wmKeyMap *WM_widgetgroup_keymap_common(wmKeyConfig *config, struct wmWidgetGroupType *wgroup); + struct wmWidgetMapType *WM_widgetmaptype_find(const char *idname, const int spaceid, const int regionid, const bool is_3d, const bool create); -struct wmWidgetGroupType *WM_widgetgrouptype_new(int (*poll)(const struct bContext *, struct wmWidgetGroupType *), - void (*create)(const struct bContext *, struct wmWidgetGroup *), - const struct Main *bmain, const char *mapidname, - const short spaceid, const short regionid, const bool is_3d); +struct wmWidgetGroupType *WM_widgetgrouptype_new( + int (*poll)(const struct bContext *, struct wmWidgetGroupType *), + void (*create)(const struct bContext *, struct wmWidgetGroup *), + wmKeyMap *(*keymap_init)(wmKeyConfig *, struct wmWidgetGroupType *), + const struct Main *bmain, const char *mapidname, const char *name, + const short spaceid, const short regionid, const bool is_3d); void WM_widgetgrouptype_unregister(struct bContext *C, struct Main *bmain, struct wmWidgetGroupType *wgroup); /* creates a widgetmap with all registered widgets for that type */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index b82771dbafe..a68e125cb4e 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -108,6 +108,8 @@ extern "C" { struct bContext; struct wmEvent; +struct wmKeyMap; +struct wmKeyConfig; struct wmWindowManager; struct wmOperator; struct ImBuf; @@ -684,6 +686,7 @@ typedef struct wmWidgetGroupType { struct wmWidgetGroupType *next, *prev; char idname[64]; /* MAX_NAME */ + char name[64]; /* widget group name - displayed in UI (keymap editor) */ /* poll if widgetmap should be active */ int (*poll)(const struct bContext *C, struct wmWidgetGroupType *wgrouptype) ATTR_WARN_UNUSED_RESULT; @@ -691,6 +694,12 @@ typedef struct wmWidgetGroupType { /* update widgets, called right before drawing */ void (*create)(const struct bContext *C, struct wmWidgetGroup *wgroup); + /* keymap init callback for this widgetgroup */ + struct wmKeyMap *(*keymap_init)(struct wmKeyConfig *, struct wmWidgetGroupType *); + + /* keymap created with callback from above */ + struct wmKeyMap *keymap; + /* rna for properties */ struct StructRNA *srna; @@ -722,7 +731,7 @@ typedef struct wmWidgetMap { /* selected widget for this map. */ struct wmWidget *selected_widget; - /* active group is overriding all other widgets while active */ + /* active group - set while widget is highlighted/active */ struct wmWidgetGroup *activegroup; } wmWidgetMap; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 3683ffe2590..9b875bbe16e 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -342,6 +342,7 @@ void WM_keymap_init(bContext *C) * it's persistent across sessions */ if (!(wm->defaultconf->flag & KEYCONF_INIT_DEFAULT)) { wm_window_keymap(wm->defaultconf); + wm_widgets_keymap(wm->defaultconf); ED_spacetypes_keymap(wm->defaultconf); wm->defaultconf->flag |= KEYCONF_INIT_DEFAULT; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index f8fe7e2955a..58b413c32f2 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1936,6 +1936,9 @@ static int wm_action_not_handled(int action) return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL); } +/* use old, hardcoded widget map handling - kept in case new one doesn't work out */ +//#define USE_OLD_WIDGETMAP_HANDLING + static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { #ifndef NDEBUG @@ -2066,16 +2069,59 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers } } else if (handler->widgetmap) { - wmWidgetMap *wmap = handler->widgetmap; - unsigned char part; - short event_processed = 0; - wmWidget *widget = wm_widgetmap_get_active_widget(wmap); ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); + wmWidgetMap *wmap = handler->widgetmap; + wmWidget *widget = wm_widgetmap_get_highlighted_widget(wmap); + short event_processed = 0; + unsigned char part; wm_widgetmap_handler_context(C, handler); wm_region_mouse_co(C, event); +#ifndef USE_OLD_WIDGETMAP_HANDLING + /* handle widget highlighting */ + if (event->type == MOUSEMOVE && !wm_widgetmap_get_active_widget(wmap)) { + if (wm_widgetmap_is_3d(wmap)) { + widget = wm_widget_find_highlighted_3D(wmap, C, event, &part); + wm_widgetmap_set_highlighted_widget(wmap, C, widget, part); + } + else { + widget = wm_widget_find_highlighted(wmap, C, event, &part); + wm_widgetmap_set_highlighted_widget(wmap, C, widget, part); + } + } + /* handle user configurable widgetmap keymap */ + else if (widget && wmap->activegroup) { + /* get user customized keymap from default one */ + const wmKeyMap *keymap = WM_keymap_active(wm, wmap->activegroup->type->keymap); + wmKeyMapItem *kmi; + + if (!keymap->poll || keymap->poll(C)) { + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (wm_eventmatch(event, kmi)) { + wmOperator *op = handler->op; + + /* weak, but allows interactive callback to not use rawkey */ + event->keymap_idname = kmi->idname; + + /* handler->op is called later, we want keymap op to be triggered here */ + handler->op = NULL; + action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr); + handler->op = op; + + if (action & WM_HANDLER_BREAK) { + break; + } + } + } + } + } + + UNUSED_VARS(event_processed); +#else + widget = wm_widgetmap_get_active_widget(wmap); + /* handle the widget first, before passing the event down */ switch (event->type) { case MOUSEMOVE: @@ -2140,16 +2186,19 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers break; } } - +#endif + /* restore the area */ CTX_wm_area_set(C, area); CTX_wm_region_set(C, region); if (handler->op) { +#ifdef USE_OLD_WIDGETMAP_HANDLING /* if event was processed by an active widget pass the modified event to the operator */ if (event_processed) { event->type = event_processed; } +#endif action |= wm_handler_operator_call(C, handlers, handler, event, NULL); } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 285951844b5..9064b9b4243 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -5195,6 +5195,12 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_previews_ensure); WM_operatortype_append(WM_OT_previews_clear); WM_operatortype_append(WM_OT_doc_view_manual_ui_context); + + /* widgets */ + WM_operatortype_append(WIDGETGROUP_OT_widget_set_active); + WM_operatortype_append(WIDGETGROUP_OT_widget_set_select); + WM_operatortype_append(WIDGETGROUP_OT_widget_tweak); + WM_operatortype_append(WIDGETGROUP_OT_widget_tweak_cancel); } /* circleselect-like modal operators */ diff --git a/source/blender/windowmanager/intern/wm_widgets.c b/source/blender/windowmanager/intern/wm_widgets.c index c4cb44e3ff6..78835172dbd 100644 --- a/source/blender/windowmanager/intern/wm_widgets.c +++ b/source/blender/windowmanager/intern/wm_widgets.c @@ -70,6 +70,7 @@ #include "GPU_select.h" #include "RNA_access.h" +#include "RNA_define.h" #include "BPY_extern.h" /** @@ -101,10 +102,10 @@ static ListBase widgetmaptypes = {NULL, NULL}; wmWidgetGroupType *WM_widgetgrouptype_new( int (*poll)(const bContext *C, wmWidgetGroupType *), void (*create)(const bContext *, wmWidgetGroup *), - const Main *bmain, const char *mapidname, + wmKeyMap *(*keymap_init)(wmKeyConfig *, wmWidgetGroupType *), + const Main *bmain, const char *mapidname, const char *name, const short spaceid, const short regionid, const bool is_3d) { - bScreen *sc; wmWidgetMapType *wmaptype = WM_widgetmaptype_find(mapidname, spaceid, regionid, is_3d, false); wmWidgetGroupType *wgrouptype; @@ -114,19 +115,28 @@ wmWidgetGroupType *WM_widgetgrouptype_new( } wgrouptype = MEM_callocN(sizeof(wmWidgetGroupType), "widgetgroup"); - + wgrouptype->poll = poll; wgrouptype->create = create; + wgrouptype->keymap_init = keymap_init; wgrouptype->spaceid = spaceid; wgrouptype->regionid = regionid; wgrouptype->is_3d = is_3d; - BLI_strncpy(wgrouptype->mapidname, mapidname, 64); + BLI_strncpy(wgrouptype->name, name, MAX_NAME); + BLI_strncpy(wgrouptype->mapidname, mapidname, MAX_NAME); /* add the type for future created areas of the same type */ BLI_addtail(&wmaptype->widgetgrouptypes, wgrouptype); - - /* now create a widget for all existing areas. (main is missing when we create new areas so not needed) */ + + /* main is missing on startup when we create new areas */ if (bmain) { + wmWindowManager *wm = bmain->wm.first; + bScreen *sc; + + /* init keymap - on startup there's an extra call to init keymaps for 'permanent' widgets */ + wm_widgetgrouptype_keymap_init(wgrouptype, wm->defaultconf); + + /* now create a widget for all existing areas */ for (sc = bmain->screen.first; sc; sc = sc->id.next) { ScrArea *sa; for (sa = sc->areabase.first; sa; sa = sa->next) { @@ -209,6 +219,21 @@ static void widget_calculate_scale(wmWidget *widget, const bContext *C) widget->scale = scale * widget->user_scale; } +/** + * Initialize keymaps for all existing widget-groups + */ +void wm_widgets_keymap(wmKeyConfig *keyconf) +{ + wmWidgetMapType *wmaptype; + wmWidgetGroupType *wgrouptype; + + for (wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) { + for (wgrouptype = wmaptype->widgetgrouptypes.first; wgrouptype; wgrouptype = wgrouptype->next) { + wm_widgetgrouptype_keymap_init(wgrouptype, keyconf); + } + } +} + BLI_INLINE bool widgets_compare(const wmWidget *a, const wmWidget *b) { return STREQ(a->idname, b->idname); @@ -399,6 +424,21 @@ static void widget_unique_idname_set(wmWidgetGroup *wgroup, wmWidget *widget, co } /** + * Search for an active widget in region \a ar + */ +static wmWidget *widget_find_active_in_region(const ARegion *ar, wmWidgetMap **r_wmap) +{ + for (*r_wmap = ar->widgetmaps.first; *r_wmap; *r_wmap = (*r_wmap)->next) { + if ((*r_wmap)->active_widget) { + return (*r_wmap)->active_widget; + } + } + + *r_wmap = NULL; + return NULL; +} + +/** * Register \a widget * * \param name name used to create a unique idname for \a widget in \a wgroup @@ -423,7 +463,9 @@ bool wm_widget_register(wmWidgetGroup *wgroup, wmWidget *widget, const char *nam widget->props = MEM_callocN(sizeof(PropertyRNA *) * widget->max_prop, "widget->props"); widget->ptr = MEM_callocN(sizeof(PointerRNA) * widget->max_prop, "widget->ptr"); - + + widget->wgroup = wgroup; + BLI_addtail(&wgroup->widgets, widget); return true; } @@ -505,6 +547,162 @@ void WM_widget_set_colors(wmWidget *widget, const float col[4], const float col_ } +/** \name Widget operators + * + * Basic operators for widget interaction with user configurable keymaps. + * + * \{ */ + +static int widget_set_active_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + wmWidgetMap *wmap; + const bool deactivate = RNA_boolean_get(op->ptr, "deactivate"); + + for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) { + if (deactivate) { + wm_widgetmap_set_active_widget(wmap, C, event, NULL); + + /* ugly hack - send widget release event */ + ((wmEvent *)event)->type = EVT_WIDGET_RELEASED; + } + else { + wmWidget *widget = wmap->highlighted_widget; + if (widget) { + wm_widgetmap_set_active_widget(wmap, C, event, widget); + break; + } + else { + BLI_assert(0); + return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); + } + } + } + + return OPERATOR_FINISHED; +} + +void WIDGETGROUP_OT_widget_set_active(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Widget Activate"; + ot->description = "Activate the currently highlighted widget"; + ot->idname = "WIDGETGROUP_OT_widget_set_active"; + + /* api callbacks */ + ot->invoke = widget_set_active_invoke; + + ot->flag = OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "deactivate", 0, "Deactivate", "Deactivate currently active widget"); +} + +static int widget_set_select_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) +{ + ARegion *ar = CTX_wm_region(C); + wmWidgetMap *wmap; + + for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) { + wmWidget *widget = wmap->highlighted_widget; + if (widget) { + if (widget->flag & WM_WIDGET_SELECTABLE) { + wm_widgetmap_set_selected_widget(C, wmap, widget); + } + break; + } + else { + BLI_assert(0); + return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); + } + } + + return OPERATOR_FINISHED; +} + +void WIDGETGROUP_OT_widget_set_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Widget Select"; + ot->description = "Select the currently highlighted widget"; + ot->idname = "WIDGETGROUP_OT_widget_set_select"; + + /* api callbacks */ + ot->invoke = widget_set_select_invoke; + + ot->flag = OPTYPE_UNDO; + + /* TODO - more fancy selections are not implemented yet */ +// RNA_def_boolean(ot->srna, "deactivate", 0, "Deactivate", "Deactivate currently active widget"); +} + +static int widget_tweak_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + wmWidgetMap *wmap; + wmWidget *widget = widget_find_active_in_region(ar, &wmap); + + if (!widget) { + BLI_assert(0); + return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); + } + + /* ugly hack - send widget update event */ + ((wmEvent *)event)->type = EVT_WIDGET_UPDATE; + + /* handle widget */ + widget->handler(C, event, widget); + + return OPERATOR_FINISHED; +} + +void WIDGETGROUP_OT_widget_tweak(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Widget Tweak"; + ot->description = "Tweak the active widget"; + ot->idname = "WIDGETGROUP_OT_widget_tweak"; + + /* api callbacks */ + ot->invoke = widget_tweak_invoke; +} + +static int widget_cancel_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + wmWidgetMap *wmap; + wmWidget *widget = widget_find_active_in_region(ar, &wmap); + + if (!widget) { + /* don't assert(0) here, this might be called if modal handler + * which has widget attached uses same shortcut as widget-cancel */ + return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); + } + + if (widget->cancel) { + widget->cancel(C, widget); + } + wm_widgetmap_set_active_widget(wmap, C, event, NULL); + + /* ugly hack - send widget release event */ + ((wmEvent *)event)->type = EVT_WIDGET_RELEASED; + + return OPERATOR_FINISHED; +} + +void WIDGETGROUP_OT_widget_tweak_cancel(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Widget Tweak Cancel"; + ot->description = "Cancel tweaking of active widget"; + ot->idname = "WIDGETGROUP_OT_widget_tweak_cancel"; + + /* api callbacks */ + ot->invoke = widget_cancel_invoke; +} + +/** \} */ // Widget operators + + wmWidgetMapType *WM_widgetmaptype_find( const char *idname, const int spaceid, const int regionid, const bool is_3d, const bool create) { @@ -724,15 +922,19 @@ void wm_widgetmap_set_highlighted_widget(wmWidgetMap *wmap, bContext *C, wmWidge if (widget) { widget->flag |= WM_WIDGET_HIGHLIGHT; widget->highlighted_part = part; - + wmap->activegroup = widget->wgroup; + if (C && widget->get_cursor) { wmWindow *win = CTX_wm_window(C); WM_cursor_set(win, widget->get_cursor(widget)); } } - else if (C) { - wmWindow *win = CTX_wm_window(C); - WM_cursor_set(win, CURSOR_STD); + else { + wmap->activegroup = NULL; + if (C) { + wmWindow *win = CTX_wm_window(C); + WM_cursor_set(win, CURSOR_STD); + } } /* tag the region for redraw */ @@ -750,16 +952,13 @@ wmWidget *wm_widgetmap_get_highlighted_widget(wmWidgetMap *wmap) void wm_widgetmap_set_active_widget( wmWidgetMap *wmap, bContext *C, - wmEvent *event, wmWidget *widget, - const bool call_op) + const wmEvent *event, wmWidget *widget) { if (widget) { - if (call_op) { + if (widget->opname) { wmOperatorType *ot; - const bool has_custom_op = widget->opname != NULL; - const char *opname = has_custom_op ? widget->opname : "WM_OT_widget_tweak"; - ot = WM_operatortype_find(opname, 0); + ot = WM_operatortype_find(widget->opname, 0); if (ot) { /* first activate the widget itself */ @@ -769,16 +968,7 @@ void wm_widgetmap_set_active_widget( } wmap->active_widget = widget; - /* if operator runs modal, we will need to activate the current widgetmap on the operator handler, - * so it can process events first, then pass them on to the operator */ - if (WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &widget->opptr) == OPERATOR_RUNNING_MODAL) { - /* check if operator added a a modal event handler */ - wmEventHandler *handler = CTX_wm_window(C)->modalhandlers.first; - - if (has_custom_op == false && handler && handler->op && handler->op->type == ot) { - handler->widgetmap = wmap; - } - } + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &widget->opptr); /* we failed to hook the widget to the operator handler or operator was cancelled, return */ if (!wmap->active_widget) { @@ -914,7 +1104,7 @@ void wm_widget_handler_modal_update(bContext *C, wmEvent *event, wmEventHandler } /* operator not running anymore */ else { - wm_widgetmap_set_active_widget(wmap, C, event, NULL, false); + wm_widgetmap_set_active_widget(wmap, C, event, NULL); } /* restore the area */ @@ -980,7 +1170,7 @@ static void wm_widgetgroup_free(bContext *C, wmWidgetMap *wmap, wmWidgetGroup *w wm_widgetmap_set_highlighted_widget(wmap, C, NULL, 0); } if (widget->flag & WM_WIDGET_ACTIVE) { - wm_widgetmap_set_active_widget(wmap, C, NULL, NULL, false); + wm_widgetmap_set_active_widget(wmap, C, NULL, NULL); } wm_widget_delete(&wgroup->widgets, widget); widget = widget_next; @@ -1003,6 +1193,34 @@ static void wm_widgetgroup_free(bContext *C, wmWidgetMap *wmap, wmWidgetGroup *w MEM_freeN(wgroup); } +/** + * Common default keymap for widget groups + */ +wmKeyMap *WM_widgetgroup_keymap_common(wmKeyConfig *config, wmWidgetGroupType *wgrouptype) +{ + wmKeyMap *km = WM_keymap_find(config, wgrouptype->name, 0, 0); + wmKeyMapItem *kmi; + + kmi = WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_set_active", ACTIONMOUSE, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "deactivate", false); + kmi = WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_set_active", ACTIONMOUSE, KM_RELEASE, 0, 0); + RNA_boolean_set(kmi->ptr, "deactivate", true); + + WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_tweak", MOUSEMOVE, KM_ANY, KM_ANY, 0); + + WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_tweak_cancel", RIGHTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_tweak_cancel", ESCKEY, KM_PRESS, 0, 0); + + WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_set_select", SELECTMOUSE, KM_PRESS, 0, 0); + + return km; +} + +void wm_widgetgrouptype_keymap_init(wmWidgetGroupType *wgrouptype, wmKeyConfig *keyconf) +{ + wgrouptype->keymap = wgrouptype->keymap_init(keyconf, wgrouptype); +} + void WM_widgetgrouptype_unregister(bContext *C, Main *bmain, wmWidgetGroupType *wgrouptype) { bScreen *sc; diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index 56dec199191..6dbe3617852 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -55,6 +55,9 @@ typedef struct wmWidget { char idname[MAX_NAME + 4]; /* + 4 for unique '.001', '.002', etc suffix */ + /* pointer back to parent widget group */ + wmWidgetGroup *wgroup; + /* draw widget */ void (*draw)(const struct bContext *C, struct wmWidget *widget); /* determine if the mouse intersects with the widget. The calculation should be done in the callback itself */ @@ -168,6 +171,12 @@ void wm_open_init_use_scripts(wmOperator *op, bool use_prefs); /* wm_widgets.c */ bool wm_widgetmap_is_3d(const struct wmWidgetMap *wmap); bool wm_widget_register(struct wmWidgetGroup *wgroup, struct wmWidget *widget, const char *name); +void wm_widgets_keymap(wmKeyConfig *keyconf); + +void WIDGETGROUP_OT_widget_set_active(wmOperatorType *ot); +void WIDGETGROUP_OT_widget_set_select(wmOperatorType *ot); +void WIDGETGROUP_OT_widget_tweak(wmOperatorType *ot); +void WIDGETGROUP_OT_widget_tweak_cancel(wmOperatorType *ot); /* hack to store circle select size - campbell, must replace with nice operator memory */ diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index 2189b7f9112..14f571b89ce 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -104,12 +104,14 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect); void wm_widget_handler_modal_update(bContext *C, wmEvent *event, wmEventHandler *handler); void wm_widgetmap_handler_context(bContext *C, wmEventHandler *handler); +void wm_widgetgrouptype_keymap_init(wmWidgetGroupType *wgrouptype, wmKeyConfig *keyconf); + struct wmWidget *wm_widget_find_highlighted_3D(struct wmWidgetMap *wmap, struct bContext *C, const struct wmEvent *event, unsigned char *part); wmWidget *wm_widget_find_highlighted(struct wmWidgetMap *wmap, bContext *C, const struct wmEvent *event, unsigned char *part); void wm_widgetmap_set_highlighted_widget(struct wmWidgetMap *wmap, struct bContext *C, struct wmWidget *widget, unsigned char part); struct wmWidget *wm_widgetmap_get_highlighted_widget(struct wmWidgetMap *wmap); -void wm_widgetmap_set_active_widget(struct wmWidgetMap *wmap, struct bContext *C, struct wmEvent *event, struct wmWidget *widget, const bool call_op); +void wm_widgetmap_set_active_widget(struct wmWidgetMap *wmap, struct bContext *C, const struct wmEvent *event, struct wmWidget *widget); struct wmWidget *wm_widgetmap_get_active_widget(struct wmWidgetMap *wmap); void wm_widgetmap_set_selected_widget(struct bContext *C, wmWidgetMap *wmap, wmWidget *widget); |