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:
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);