diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_widgets.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_widgets.c | 566 |
1 files changed, 396 insertions, 170 deletions
diff --git a/source/blender/windowmanager/intern/wm_widgets.c b/source/blender/windowmanager/intern/wm_widgets.c index b32fa7b78e0..613d20c14f8 100644 --- a/source/blender/windowmanager/intern/wm_widgets.c +++ b/source/blender/windowmanager/intern/wm_widgets.c @@ -15,8 +15,7 @@ * 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 but based - * on ghostwinlay.c (C) 2001-2002 by NaN Holding BV + * The Original Code is Copyright (C) 2014 Blender Foundation. * All rights reserved. * * Contributor(s): Blender Foundation, 2008 @@ -70,6 +69,7 @@ #include "GPU_select.h" #include "RNA_access.h" +#include "RNA_define.h" #include "BPY_extern.h" /** @@ -101,60 +101,73 @@ 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 *, const char *), + 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; - + bScreen *sc; + if (!wmaptype) { fprintf(stderr, "widgetgrouptype creation: widgetmap type does not exist"); return NULL; } - + 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) */ - if (bmain) { - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - ScrArea *sa; - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - - for (sl = sa->spacedata.first; sl; sl = sl->next) { - ARegion *ar; - ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase; - - for (ar = lb->first; ar; ar = ar->next) { - wmWidgetMap *wmap; - for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) { - if (wmap->type == wmaptype) { - wmWidgetGroup *wgroup = MEM_callocN(sizeof(wmWidgetGroup), "widgetgroup"); - wgroup->type = wgrouptype; - - /* just add here, drawing will occur on next update */ - BLI_addtail(&wmap->widgetgroups, wgroup); - wm_widgetmap_set_highlighted_widget(wmap, NULL, NULL, 0); - ED_region_tag_redraw(ar); - } + + /* Main is missing on startup when we create new areas. + * So this is only called for widgets initialized on runtime */ + if (!bmain) + return wgrouptype; + + + /* init keymap - on startup there's an extra call to init keymaps for 'permanent' widget-groups */ + wm_widgetgrouptype_keymap_init(wgrouptype, ((wmWindowManager *)bmain->wm.first)->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) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + ARegion *ar; + ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase; + + for (ar = lb->first; ar; ar = ar->next) { + wmWidgetMap *wmap; + + for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) { + if (wmap->type == wmaptype) { + wmWidgetGroup *wgroup = MEM_callocN(sizeof(wmWidgetGroup), "widgetgroup"); + + wgroup->type = wgrouptype; + + /* just add here, drawing will occur on next update */ + BLI_addtail(&wmap->widgetgroups, wgroup); + wm_widgetmap_set_highlighted_widget(wmap, NULL, NULL, 0); + ED_region_tag_redraw(ar); } } } } } } - + return wgrouptype; } @@ -164,9 +177,9 @@ wmWidget *WM_widget_new(void (*draw)(const bContext *C, wmWidget *customdata), int (*handler)(bContext *C, const wmEvent *event, wmWidget *widget)) { wmWidget *widget; - + widget = MEM_callocN(sizeof(wmWidget), "widget"); - + widget->draw = draw; widget->handler = handler; widget->intersect = intersect; @@ -175,50 +188,6 @@ wmWidget *WM_widget_new(void (*draw)(const bContext *C, wmWidget *customdata), return widget; } -void WM_widget_property(wmWidget *widget, const int slot, PointerRNA *ptr, const char *propname) -{ - if (slot < 0 || slot >= widget->max_prop) { - fprintf(stderr, "invalid index %d when binding property for widget type %s\n", slot, widget->idname); - return; - } - - /* if widget evokes an operator we cannot use it for property manipulation */ - widget->opname = NULL; - widget->ptr[slot] = *ptr; - widget->props[slot] = RNA_struct_find_property(ptr, propname); - - if (widget->bind_to_prop) - widget->bind_to_prop(widget, slot); -} - -PointerRNA *WM_widget_operator(wmWidget *widget, const char *opname) -{ - wmOperatorType *ot = WM_operatortype_find(opname, 0); - - if (ot) { - widget->opname = opname; - - WM_operator_properties_create_ptr(&widget->opptr, ot); - - return &widget->opptr; - } - else { - fprintf(stderr, "Error binding operator to widget: operator %s not found!\n", opname); - } - - return NULL; -} - -void WM_widgetgroup_customdata_set(wmWidgetGroup *wgroup, void *data) -{ - wgroup->customdata = data; -} - -void *WM_widgetgroup_customdata(const wmWidgetGroup *wgroup) -{ - return wgroup->customdata; -} - static void wm_widget_delete(ListBase *widgetlist, wmWidget *widget) { @@ -228,7 +197,7 @@ static void wm_widget_delete(ListBase *widgetlist, wmWidget *widget) MEM_freeN(widget->props); MEM_freeN(widget->ptr); - + BLI_freelinkN(widgetlist, widget); } @@ -239,8 +208,6 @@ static void widget_calculate_scale(wmWidget *widget, const bContext *C) float scale = 1.0f; if (rv3d && (U.tw_flag & V3D_3D_WIDGETS) == 0 && (widget->flag & WM_WIDGET_SCALE_3D)) { - ED_view3d_update_viewmat(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), NULL, NULL); - if (widget->get_final_position) { float position[3]; @@ -255,7 +222,22 @@ static void widget_calculate_scale(wmWidget *widget, const bContext *C) widget->scale = scale * widget->user_scale; } -static bool widgets_compare(const wmWidget *a, const wmWidget *b) +/** + * 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); } @@ -276,16 +258,18 @@ void WM_widgets_update(const bContext *C, wmWidgetMap *wmap) wmWidgetGroup *wgroup; for (wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) { - if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) - { + if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) { wmWidget *highlighted = NULL; /* first delete and recreate the widgets */ for (widget = wgroup->widgets.first; widget;) { wmWidget *widget_next = widget->next; + if (widget == wmap->selected_widget) { + /* skip */ + } /* do not delete the highlighted widget, instead keep it to compare with the new one */ - if (widget->flag & WM_WIDGET_HIGHLIGHT) { + else if (widget->flag & WM_WIDGET_HIGHLIGHT) { highlighted = widget; BLI_remlink(&wgroup->widgets, widget); widget->next = widget->prev = NULL; @@ -356,17 +340,18 @@ void WM_widgets_draw(const bContext *C, const wmWidgetMap *wmap, const bool in_s widget = wmap->active_widget; - if (widget && in_scene == ((widget->flag & WM_WIDGET_SCENE_DEPTH)!= 0)) { - /* notice that we don't update the widgetgroup, widget is now on its own, it should have all - * relevant data to update itself */ - widget->draw(C, widget); + if (widget && in_scene == ((widget->flag & WM_WIDGET_SCENE_DEPTH) != 0)) { + if (widget->flag & WM_WIDGET_DRAW_ACTIVE) { + /* notice that we don't update the widgetgroup, widget is now on + * its own, it should have all relevant data to update itself */ + widget->draw(C, widget); + } } else if (wmap->widgetgroups.first) { wmWidgetGroup *wgroup; - + for (wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) { - if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) - { + if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) { for (widget = wgroup->widgets.first; widget; widget = widget->next) { if ((widget->flag & WM_WIDGET_HIDDEN) == 0 && (!(widget->flag & WM_WIDGET_DRAW_HOVER) || (widget->flag & WM_WIDGET_HIGHLIGHT)) && @@ -379,6 +364,13 @@ void WM_widgets_draw(const bContext *C, const wmWidgetMap *wmap, const bool in_s } } + /* draw selected widgets last */ + if ((widget = wmap->selected_widget) && in_scene == ((widget->flag & WM_WIDGET_SCENE_DEPTH) != 0)) { + /* notice that we don't update the widgetgroup, widget is now on + * its own, it should have all relevant data to update itself */ + widget->draw(C, widget); + } + if (use_lighting) glPopAttrib(); } @@ -387,10 +379,10 @@ void WM_event_add_area_widgetmap_handlers(ARegion *ar) { wmWidgetMap *wmap; wmEventHandler *handler; - + for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) { handler = MEM_callocN(sizeof(wmEventHandler), "widget handler"); - + handler->widgetmap = wmap; BLI_addtail(&ar->handlers, handler); } @@ -411,7 +403,7 @@ void WM_modal_handler_attach_widgetgroup( wmWidgetMap *wmap; for (wmap = handler->op_region->widgetmaps.first; wmap; wmap = wmap->next) { wmWidgetMapType *wmaptype = wmap->type; - + if (wmaptype->spaceid == wgrouptype->spaceid && wmaptype->regionid == wgrouptype->regionid) { handler->widgetmap = wmap; } @@ -435,6 +427,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 @@ -456,60 +463,70 @@ bool wm_widget_register(wmWidgetGroup *wgroup, wmWidget *widget, const char *nam if (widget->max_prop == 0) { widget->max_prop = 1; } - + 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; } -void WM_widget_set_origin(wmWidget *widget, const float origin[3]) +void WM_widget_set_property(wmWidget *widget, const int slot, PointerRNA *ptr, const char *propname) { - copy_v3_v3(widget->origin, origin); + if (slot < 0 || slot >= widget->max_prop) { + fprintf(stderr, "invalid index %d when binding property for widget type %s\n", slot, widget->idname); + return; + } + + /* if widget evokes an operator we cannot use it for property manipulation */ + widget->opname = NULL; + widget->ptr[slot] = *ptr; + widget->props[slot] = RNA_struct_find_property(ptr, propname); + + if (widget->bind_to_prop) + widget->bind_to_prop(widget, slot); } -void WM_widget_set_3d_scale(wmWidget *widget, const bool scale) +PointerRNA *WM_widget_set_operator(wmWidget *widget, const char *opname) { - if (scale) { - widget->flag |= WM_WIDGET_SCALE_3D; + wmOperatorType *ot = WM_operatortype_find(opname, 0); + + if (ot) { + widget->opname = opname; + + WM_operator_properties_create_ptr(&widget->opptr, ot); + + return &widget->opptr; } else { - widget->flag &= ~WM_WIDGET_SCALE_3D; + fprintf(stderr, "Error binding operator to widget: operator %s not found!\n", opname); } + + return NULL; } -void WM_widget_flag_set(wmWidget *widget, const int flag, const bool enable) +void WM_widget_set_origin(wmWidget *widget, const float origin[3]) { - if (enable) { - widget->flag |= flag; - } - else { - widget->flag &= ~flag; - } + copy_v3_v3(widget->origin, origin); } -void WM_widget_set_draw_on_hover_only(wmWidget *widget, const bool draw) +void WM_widget_set_offset(wmWidget *widget, const float offset[3]) { - if (draw) { - widget->flag |= WM_WIDGET_DRAW_HOVER; - } - else { - widget->flag &= ~WM_WIDGET_DRAW_HOVER; - } + copy_v3_v3(widget->offset, offset); } -void WM_widget_set_scene_depth(wmWidget *widget, const bool scene) +void WM_widget_set_flag(wmWidget *widget, const int flag, const bool enable) { - if (scene) { - widget->flag |= WM_WIDGET_SCENE_DEPTH; + if (enable) { + widget->flag |= flag; } else { - widget->flag &= ~WM_WIDGET_SCENE_DEPTH; + widget->flag &= ~flag; } } - void WM_widget_set_scale(wmWidget *widget, const float scale) { widget->user_scale = scale; @@ -524,7 +541,7 @@ void WM_widget_set_line_width(wmWidget *widget, const float line_width) * Set widget rgba colors * * \param col Normal state color - * \param col_hi Highlighted state color + * \param col_hi Highlighted state color */ void WM_widget_set_colors(wmWidget *widget, const float col[4], const float col_hi[4]) { @@ -533,14 +550,173 @@ 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); + } + + /* handle widget */ + widget->handler(C, event, widget); + + /* ugly hack - send widget update event */ + ((wmEvent *)event)->type = EVT_WIDGET_UPDATE; + + 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) { wmWidgetMapType *wmaptype; for (wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) { - if (wmaptype->spaceid == spaceid && wmaptype->regionid == regionid && wmaptype->is_3d == is_3d - && strcmp(wmaptype->idname, idname) == 0) { + if (wmaptype->spaceid == spaceid && + wmaptype->regionid == regionid && + wmaptype->is_3d == is_3d && + STREQ(wmaptype->idname, idname)) + { return wmaptype; } } @@ -553,14 +729,14 @@ wmWidgetMapType *WM_widgetmaptype_find( wmaptype->is_3d = is_3d; BLI_strncpy(wmaptype->idname, idname, 64); BLI_addhead(&widgetmaptypes, wmaptype); - + return wmaptype; } void WM_widgetmaptypes_free(void) { wmWidgetMapType *wmaptype; - + for (wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) { BLI_freelistN(&wmaptype->widgetgrouptypes); } @@ -602,38 +778,38 @@ static int wm_widget_find_highlighted_3D_intern( const bool do_passes = GPU_select_query_check_active(); extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect); - + + rect.xmin = event->mval[0] - hotspot; rect.xmax = event->mval[0] + hotspot; rect.ymin = event->mval[1] - hotspot; rect.ymax = event->mval[1] + hotspot; - + selrect = rect; - + view3d_winmatrix_set(ar, v3d, &rect); mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - + if (do_passes) GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0); else GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_ALL, 0); /* do the drawing */ widget_find_active_3D_loop(C, visible_widgets); - + hits = GPU_select_end(); - + if (do_passes) { GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits); widget_find_active_3D_loop(C, visible_widgets); GPU_select_end(); } - + view3d_winmatrix_set(ar, v3d, NULL); mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); if (hits == 1) { return buffer[3]; - } /* find the widget the value belongs to */ else if (hits > 1) { @@ -655,6 +831,7 @@ static int wm_widget_find_highlighted_3D_intern( return minval; } + return -1; } @@ -686,24 +863,24 @@ wmWidget *wm_widget_find_highlighted_3D(wmWidgetMap *wmap, bContext *C, const wm *part = 0; /* set up view matrices */ view3d_operator_needs_opengl(C); - + ret = wm_widget_find_highlighted_3D_intern(&visible_widgets, C, event, 0.5f * hotspot); - + if (ret != -1) { LinkData *link; int retsec; retsec = wm_widget_find_highlighted_3D_intern(&visible_widgets, C, event, 0.2f * hotspot); - + if (retsec != -1) ret = retsec; - + link = BLI_findlink(&visible_widgets, ret >> 8); *part = ret & 255; result = link->data; } BLI_freelistN(&visible_widgets); - + return result; } @@ -735,7 +912,7 @@ bool WM_widgetmap_cursor_set(const wmWidgetMap *wmap, wmWindow *win) return true; } } - + return false; } @@ -746,23 +923,27 @@ void wm_widgetmap_set_highlighted_widget(wmWidgetMap *wmap, bContext *C, wmWidge wmap->highlighted_widget->flag &= ~WM_WIDGET_HIGHLIGHT; wmap->highlighted_widget->highlighted_part = 0; } - + wmap->highlighted_widget = widget; - + 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 */ if (C) { ARegion *ar = CTX_wm_region(C); @@ -778,35 +959,23 @@ 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 */ if (widget->invoke && widget->handler) { widget->flag |= WM_WIDGET_ACTIVE; widget->invoke(C, event, widget); - wmap->active_widget = 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) { @@ -846,7 +1015,7 @@ void wm_widgetmap_set_active_widget( } } wmap->active_widget = NULL; - + if (C) { ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); @@ -855,6 +1024,33 @@ void wm_widgetmap_set_active_widget( } } +wmWidget *wm_widgetmap_get_selected_widget(wmWidgetMap *wmap) +{ + return wmap->selected_widget; +} + +void wm_widgetmap_set_selected_widget(bContext *C, wmWidgetMap *wmap, wmWidget *widget) +{ + if (widget) { + wmap->selected_widget = widget; + widget->flag |= WM_WIDGET_SELECTED; + wm_widgetmap_set_highlighted_widget(wmap, C, NULL, wmap->highlighted_widget->highlighted_part); + } + else { + widget = wmap->selected_widget; + if (widget) { + wmap->selected_widget = NULL; + widget->flag &= ~WM_WIDGET_SELECTED; + } + } + + /* tag the region for redraw */ + if (C) { + ARegion *ar = CTX_wm_region(C); + ED_region_tag_redraw(ar); + } +} + void wm_widgetmap_handler_context(bContext *C, wmEventHandler *handler) { bScreen *screen = CTX_wm_screen(C); @@ -915,7 +1111,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 */ @@ -959,7 +1155,7 @@ void WM_widgetmap_delete(wmWidgetMap *wmap) for (wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) { wmWidget *widget; - + for (widget = wgroup->widgets.first; widget;) { wmWidget *widget_next = widget->next; wm_widget_delete(&wgroup->widgets, widget); @@ -981,7 +1177,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; @@ -1004,6 +1200,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, const char *wgroupname) +{ + wmKeyMap *km = WM_keymap_find(config, wgroupname, 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->name); +} + void WM_widgetgrouptype_unregister(bContext *C, Main *bmain, wmWidgetGroupType *wgrouptype) { bScreen *sc; @@ -1036,8 +1260,10 @@ void WM_widgetgrouptype_unregister(bContext *C, Main *bmain, wmWidgetGroupType * } wmaptype = WM_widgetmaptype_find(wgrouptype->mapidname, wgrouptype->spaceid, wgrouptype->regionid, wgrouptype->is_3d, false); + BLI_remlink(&wmaptype->widgetgrouptypes, wgrouptype); wgrouptype->prev = wgrouptype->next = NULL; + MEM_freeN(wgrouptype); } |