Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2015-09-25 01:07:46 +0300
committerJulian Eisel <eiseljulian@gmail.com>2015-09-25 01:07:46 +0300
commit3b29e53626f9044ce6e5b75ca1c91bf467c493d1 (patch)
tree71b74114d24bea0c7013cc1a8253979b2e6eb40e /source
parent97eed9b85b52dfdb5e931c00427e846776eb0b37 (diff)
Initial support for custom keymaps per widget group
This adds widget-group level, configurable keymaps. This means, for each widget group (e.g. Manipulator Widgets, Camera Widgets, etc), 6 keymap entries are added: * Widget Activate (action-mouse down) * Widget Activate (actually deactivate - action-mouse up) * Widget Tweak (mouse move) * Widget Tweak Cancel (RMB) * Widget Tweak Cancel (esc) * Widget Select (only for selectable widgets - select-mouse) This might be useful e.g. to set certain widgets to activate on tweak event only to resove conflicts (see manipulator vs. selection with LMB-select conflict), and for things like setting a widget values using shortcuts (not yet possible, but easy to add now). Further, this greatly improves the IMHO current ugliest part of the widget backend, the event system part/hack :P \o/ One remaining issue is that the keymap items only appear using search, they are not displayed in the keymap editor list by default (didn't investigate yet). Old functionality was ported over to new system, everything should work fine still.
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/object/object_edit.c5
-rw-r--r--source/blender/editors/space_graph/graph_edit.c5
-rw-r--r--source/blender/editors/space_node/space_node.c6
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c11
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c25
-rw-r--r--source/blender/makesrna/intern/rna_wm.c2
-rw-r--r--source/blender/windowmanager/WM_api.h12
-rw-r--r--source/blender/windowmanager/WM_types.h11
-rw-r--r--source/blender/windowmanager/intern/wm.c1
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c59
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c6
-rw-r--r--source/blender/windowmanager/intern/wm_widgets.c276
-rw-r--r--source/blender/windowmanager/wm.h9
-rw-r--r--source/blender/windowmanager/wm_event_system.h4
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);