Manipulator: handle keymaps for selected items

Was only handling keymap items when the cursor
was hovering over a manipulator.
This commit is contained in:
Campbell Barton 2017-07-24 03:28:57 +10:00
parent 392b6a303e
commit c7bc2f5e87
5 changed files with 116 additions and 29 deletions

View File

@ -2172,44 +2172,88 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wm_manipulatormap_highlight_set(mmap, C, mpr, part);
}
/* handle user configurable manipulator-map keymap */
else if (mpr) {
/* get user customized keymap from default one */
const wmManipulatorGroup *highlightgroup = mpr->parent_mgroup;
const wmKeyMap *keymap = WM_keymap_active(wm, highlightgroup->type->keymap);
wmKeyMapItem *kmi;
else {
/* Either we operate on a single highlighted item
* or groups attached to the selected manipulators.
* To simplify things both cases loop over an array of items. */
wmManipulatorGroup *mgroup_first;
bool is_mgroup_single;
PRINT("%s: checking '%s' ...", __func__, keymap->idname);
if (ISMOUSE(event->type)) {
/* Keep mpr set as-is, just fake single selection. */
if (mpr) {
mgroup_first = mpr->parent_mgroup;
}
else {
mgroup_first = NULL;
}
is_mgroup_single = true;
}
else {
if (WM_manipulatormap_is_any_selected(mmap)) {
const ListBase *groups = WM_manipulatormap_group_list(mmap);
mgroup_first = groups->first;
}
else {
mgroup_first = NULL;
}
is_mgroup_single = false;
}
if (!keymap->poll || keymap->poll(C)) {
PRINT("pass\n");
for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
if (wm_eventmatch(event, kmi)) {
wmOperator *op = handler->op;
/* Don't use from now on. */
mpr = NULL;
PRINT("%s: item matched '%s'\n", __func__, kmi->idname);
for (wmManipulatorGroup *mgroup = mgroup_first; mgroup; mgroup = mgroup->next) {
/* get user customized keymap from default one */
/* weak, but allows interactive callback to not use rawkey */
event->keymap_idname = kmi->idname;
if ((is_mgroup_single == false) &&
/* We might want to change the logic here and use some kind of manipulator edit-mode.
* For now just use keymap when a selection exists. */
wm_manipulatorgroup_is_any_selected(mgroup) == false)
{
continue;
}
/* 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;
const wmKeyMap *keymap = WM_keymap_active(wm, mgroup->type->keymap);
wmKeyMapItem *kmi;
if (action & WM_HANDLER_BREAK) {
if (action & WM_HANDLER_HANDLED) {
if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
}
else {
PRINT("%s: un-handled '%s'\n", __func__, kmi->idname);
PRINT("%s: checking '%s' ...", __func__, keymap->idname);
if (!keymap->poll || keymap->poll(C)) {
PRINT("pass\n");
for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
if (wm_eventmatch(event, kmi)) {
wmOperator *op = handler->op;
PRINT("%s: item matched '%s'\n", __func__, kmi->idname);
/* 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) {
if (action & WM_HANDLER_HANDLED) {
if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
}
else {
PRINT("%s: un-handled '%s'\n", __func__, kmi->idname);
}
}
}
}
}
}
else {
PRINT("fail\n");
else {
PRINT("fail\n");
}
if (is_mgroup_single) {
break;
}
}
}

View File

@ -206,6 +206,7 @@ void WM_manipulatormap_draw(struct wmManipulatorMap *mmap, const struct bContext
void WM_manipulatormap_add_handlers(struct ARegion *ar, struct wmManipulatorMap *mmap);
bool WM_manipulatormap_select_all(struct bContext *C, struct wmManipulatorMap *mmap, const int action);
bool WM_manipulatormap_cursor_set(const struct wmManipulatorMap *mmap, struct wmWindow *win);
bool WM_manipulatormap_is_any_selected(const struct wmManipulatorMap *mmap);
/* -------------------------------------------------------------------- */
/* wmManipulatorMapType */
@ -238,7 +239,9 @@ void WM_manipulatormaptype_group_unlink(
void WM_manipulatormaptype_group_free(struct wmManipulatorGroupTypeRef *wgt);
/* -------------------------------------------------------------------- */
/* Manipulator Add/Remove (High level API) */
/* ManipulatorGroup */
/* Add/Remove (High level API) */
void WM_manipulator_group_add_ptr_ex(
struct wmManipulatorGroupType *wgt,
@ -261,4 +264,7 @@ void WM_manipulator_group_remove_ptr_delayed(
struct wmManipulatorGroupType *wgt);
void WM_manipulator_group_remove_delayed(const char *idname);
/* Utilities */
void WM_manipulator_group_is_any_selected(const char *idname);
#endif /* __WM_MANIPULATOR_API_H__ */

View File

@ -202,6 +202,20 @@ bool wm_manipulatorgroup_is_visible_in_drawstep(const wmManipulatorGroup *mgroup
}
}
bool wm_manipulatorgroup_is_any_selected(const wmManipulatorGroup *mgroup)
{
if (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SELECT) {
for (const wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
if (mpr->state & WM_MANIPULATOR_STATE_SELECT) {
return true;
}
}
}
return false;
}
/** \} */
/** \name Manipulator operators
*
* Basic operators for manipulator interaction with user configurable keymaps.

View File

@ -135,11 +135,19 @@ const ListBase *WM_manipulatormap_group_list(wmManipulatorMap *mmap)
return &mmap->groups;
}
bool WM_manipulatormap_is_any_selected(const wmManipulatorMap *mmap)
{
return mmap->mmap_context.selected_len != 0;
}
/**
* Creates and returns idname hash table for (visible) manipulators in \a mmap
*
* \param poll Polling function for excluding manipulators.
* \param data Custom data passed to \a poll
*
* TODO(campbell): this uses unreliable order,
* best we use an iterator function instead of a hash.
*/
static GHash *WM_manipulatormap_manipulator_hash_new(
const bContext *C, wmManipulatorMap *mmap,
@ -754,6 +762,17 @@ wmManipulator *wm_manipulatormap_active_get(wmManipulatorMap *mmap)
return mmap->mmap_context.active;
}
wmManipulator **wm_manipulatormap_selected_get(wmManipulatorMap *mmap, int *r_selected_len)
{
*r_selected_len = mmap->mmap_context.selected_len;
return mmap->mmap_context.selected;
}
ListBase *wm_manipulatormap_groups_get(wmManipulatorMap *mmap)
{
return &mmap->groups;
}
/** \} */ /* wmManipulatorMap */

View File

@ -61,6 +61,8 @@ void wm_manipulatorgrouptype_init(void);
void MANIPULATORGROUP_OT_manipulator_select(struct wmOperatorType *ot);
void MANIPULATORGROUP_OT_manipulator_tweak(struct wmOperatorType *ot);
bool wm_manipulatorgroup_is_any_selected(const struct wmManipulatorGroup *mgroup);
/* -------------------------------------------------------------------- */
/* wmManipulatorMap */
@ -83,6 +85,8 @@ void wm_manipulatormap_active_set(
struct wmManipulatorMap *mmap, bContext *C,
const struct wmEvent *event, struct wmManipulator *mpr);
struct wmManipulator *wm_manipulatormap_active_get(struct wmManipulatorMap *mmap);
struct wmManipulator **wm_manipulatormap_selected_get(wmManipulatorMap *mmap, int *r_selected_len);
struct ListBase *wm_manipulatormap_groups_get(wmManipulatorMap *mmap);
/* -------------------------------------------------------------------- */
/* wmManipulatorMapType */