diff options
9 files changed, 122 insertions, 18 deletions
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index c0cdce1b000..2f93be8ae38 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -464,7 +464,8 @@ static void IMAGE_GGT_gizmo2d(wmGizmoGroupType *gzgt) gzgt->name = "UV Transform Gizmo"; gzgt->idname = "IMAGE_GGT_gizmo2d"; - gzgt->flag |= WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_IMAGE; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -481,7 +482,8 @@ static void IMAGE_GGT_gizmo2d_translate(wmGizmoGroupType *gzgt) gzgt->name = "UV Translate Gizmo"; gzgt->idname = "IMAGE_GGT_gizmo2d_translate"; - gzgt->flag |= WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_IMAGE; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -498,7 +500,8 @@ static void IMAGE_GGT_gizmo2d_resize(wmGizmoGroupType *gzgt) gzgt->name = "UV Transform Gizmo Resize"; gzgt->idname = "IMAGE_GGT_gizmo2d_resize"; - gzgt->flag |= WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_IMAGE; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -515,7 +518,8 @@ static void IMAGE_GGT_gizmo2d_rotate(wmGizmoGroupType *gzgt) gzgt->name = "UV Transform Gizmo Resize"; gzgt->idname = "IMAGE_GGT_gizmo2d_rotate"; - gzgt->flag |= WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_IMAGE; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c index f761a44fe16..8cd5ed7a478 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c @@ -195,7 +195,8 @@ void VIEW3D_GGT_tool_generic_handle_normal(wmGizmoGroupType *gzgt) gzgt->name = "Generic Tool Widget Normal"; gzgt->idname = handle_normal_id; - gzgt->flag |= (WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP); + gzgt->flag |= (WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -211,6 +212,8 @@ void VIEW3D_GGT_tool_generic_handle_free(wmGizmoGroupType *gzgt) gzgt->name = "Generic Tool Widget Free"; gzgt->idname = handle_free_id; + /* Don't use 'WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK' here since this style of gizmo + * is better suited to being activated immediately. */ gzgt->flag |= (WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP); gzgt->gzmap_params.spaceid = SPACE_VIEW3D; diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index f19147baa89..b3c1fbd3aad 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -2046,7 +2046,8 @@ void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt) gzgt->name = "3D View: Transform Gizmo"; gzgt->idname = "VIEW3D_GGT_xform_gizmo"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -2081,7 +2082,7 @@ void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt) gzgt->idname = "VIEW3D_GGT_xform_gizmo_context"; gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; gzgt->poll = WIDGETGROUP_gizmo_poll_context; gzgt->setup = WIDGETGROUP_gizmo_setup; @@ -2289,7 +2290,8 @@ void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt) gzgt->name = "Transform Cage"; gzgt->idname = "VIEW3D_GGT_xform_cage"; - gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -2530,7 +2532,8 @@ void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt) gzgt->name = "Transform Shear"; gzgt->idname = "VIEW3D_GGT_xform_shear"; - gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c index da6b0285a5c..fb33471cf3f 100644 --- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c +++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c @@ -514,7 +514,8 @@ void VIEW3D_GGT_xform_extrude(struct wmGizmoGroupType *gzgt) gzgt->name = "3D View Extrude"; gzgt->idname = "VIEW3D_GGT_xform_extrude"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP; + gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h index a81a4596733..c2fbaaaa83c 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h @@ -280,7 +280,13 @@ const struct ListBase *WM_gizmomap_group_list(struct wmGizmoMap *gzmap); struct wmGizmoGroup *WM_gizmomap_group_find(struct wmGizmoMap *gzmap, const char *idname); struct wmGizmoGroup *WM_gizmomap_group_find_ptr(struct wmGizmoMap *gzmap, const struct wmGizmoGroupType *gzgt); + +eWM_GizmoFlagMapDrawStep WM_gizmomap_drawstep_from_gizmo_group(const struct wmGizmoGroup *gzgroup); +void WM_gizmomap_tag_refresh_drawstep(struct wmGizmoMap *gzmap, + const eWM_GizmoFlagMapDrawStep drawstep); void WM_gizmomap_tag_refresh(struct wmGizmoMap *gzmap); +bool WM_gizmomap_tag_refresh_check(struct wmGizmoMap *gzmap); + void WM_gizmomap_draw(struct wmGizmoMap *gzmap, const struct bContext *C, const eWM_GizmoFlagMapDrawStep drawstep); diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h index d3aa333daea..fc876b56de7 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h @@ -124,8 +124,21 @@ typedef enum eWM_GizmoFlagGroupTypeFlag { /** * This gizmo type supports using the fallback tools keymap. * #wmGizmoGroup.use_tool_fallback will need to be set too. + * + * Often useful in combination with #WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK */ WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP = (1 << 7), + + /** + * Use this from a gizmos refresh callback so we can postpone the refresh operation + * until the tweak operation is finished. + * Only do this when the group doesn't have a highlighted gizmo. + * + * The result for the user is tweak events delay the gizmo from flashing under the users cursor, + * for selection operations. This means gizmos that use this check don't interfere + * with click drag events by popping up under the cursor and catching the tweak event. + */ + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK = (1 << 8), } eWM_GizmoFlagGroupTypeFlag; /** @@ -447,6 +460,16 @@ typedef struct wmGizmoGroup { /** Errors and warnings storage. */ struct ReportList *reports; + /** Has the same result as hiding all gizmos individually. */ + struct { + /* Reasons for hiding. */ + union { + uint delay_refresh_for_tweak : 1; + }; + /* All, when we only want to check. */ + uint any; + } hide; + bool tag_remove; bool use_fallback_keymap; diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c index d2638ae148e..73bee883cf8 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c @@ -284,8 +284,10 @@ void WM_gizmogroup_ensure_init(const bContext *C, wmGizmoGroup *gzgroup) /* Refresh may be called multiple times, * this just ensures its called at least once before we draw. */ if (UNLIKELY((gzgroup->init_flag & WM_GIZMOGROUP_INIT_REFRESH) == 0)) { - WM_gizmo_group_refresh(C, gzgroup); + /* Clear the flag before calling refresh so the callback + * can postpone the refresh by clearing this flag. */ gzgroup->init_flag |= WM_GIZMOGROUP_INIT_REFRESH; + WM_gizmo_group_refresh(C, gzgroup); } } @@ -1147,6 +1149,26 @@ bool WM_gizmo_group_type_poll(const bContext *C, const wmGizmoGroupType *gzgt) void WM_gizmo_group_refresh(const bContext *C, wmGizmoGroup *gzgroup) { const wmGizmoGroupType *gzgt = gzgroup->type; + if (gzgt->flag & WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK) { + wmGizmoMap *gzmap = gzgroup->parent_gzmap; + wmGizmo *gz = wm_gizmomap_highlight_get(gzmap); + if (!gz || gz->parent_gzgroup != gzgroup) { + wmWindow *win = CTX_wm_window(C); + if (win->tweak) { + /* We need to run refresh again. */ + gzgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH; + WM_gizmomap_tag_refresh_drawstep(gzmap, WM_gizmomap_drawstep_from_gizmo_group(gzgroup)); + gzgroup->hide.delay_refresh_for_tweak = true; + return; + } + } + gzgroup->hide.delay_refresh_for_tweak = false; + } + + if (gzgroup->hide.any) { + return; + } + if (gzgt->refresh) { gzgt->refresh(C, gzgroup); } diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index 97bb203bcf6..f176f0e5df4 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -304,16 +304,47 @@ static GHash *WM_gizmomap_gizmo_hash_new(const bContext *C, return hash; } +eWM_GizmoFlagMapDrawStep WM_gizmomap_drawstep_from_gizmo_group(const wmGizmoGroup *gzgroup) +{ + eWM_GizmoFlagMapDrawStep step; + if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) { + step = WM_GIZMOMAP_DRAWSTEP_3D; + } + else { + step = WM_GIZMOMAP_DRAWSTEP_2D; + } + return step; +} + +void WM_gizmomap_tag_refresh_drawstep(wmGizmoMap *gzmap, const eWM_GizmoFlagMapDrawStep drawstep) +{ + BLI_assert((uint)drawstep < WM_GIZMOMAP_DRAWSTEP_MAX); + if (gzmap) { + gzmap->update_flag[drawstep] |= (GIZMOMAP_IS_PREPARE_DRAW | GIZMOMAP_IS_REFRESH_CALLBACK); + } +} + void WM_gizmomap_tag_refresh(wmGizmoMap *gzmap) { if (gzmap) { - /* We might want only to refresh some, for tag all steps. */ for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) { gzmap->update_flag[i] |= (GIZMOMAP_IS_PREPARE_DRAW | GIZMOMAP_IS_REFRESH_CALLBACK); } } } +bool WM_gizmomap_tag_refresh_check(wmGizmoMap *gzmap) +{ + if (gzmap) { + for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) { + if (gzmap->update_flag[i] & (GIZMOMAP_IS_PREPARE_DRAW | GIZMOMAP_IS_REFRESH_CALLBACK)) { + return true; + } + } + } + return false; +} + static bool gizmo_prepare_drawing(wmGizmoMap *gzmap, wmGizmo *gz, const bContext *C, @@ -359,7 +390,8 @@ static void gizmomap_prepare_drawing(wmGizmoMap *gzmap, /* only active gizmo needs updating */ if (gz_modal) { if ((gz_modal->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0) { - if (wm_gizmogroup_is_visible_in_drawstep(gz_modal->parent_gzgroup, drawstep)) { + if ((gz_modal->parent_gzgroup->hide.any == 0) && + wm_gizmogroup_is_visible_in_drawstep(gz_modal->parent_gzgroup, drawstep)) { if (gizmo_prepare_drawing(gzmap, gz_modal, C, draw_gizmos, drawstep)) { gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_PREPARE_DRAW; } @@ -369,9 +401,13 @@ static void gizmomap_prepare_drawing(wmGizmoMap *gzmap, } } + /* Allow refresh functions to ask to be refreshed again, clear before the loop below. */ + const bool do_refresh = gzmap->update_flag[drawstep] & GIZMOMAP_IS_REFRESH_CALLBACK; + gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_REFRESH_CALLBACK; + for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) { /* check group visibility - drawstep first to avoid unnecessary call of group poll callback */ - if (!wm_gizmogroup_is_visible_in_drawstep(gzgroup, drawstep) || + if ((gzgroup->hide.any != 0) || !wm_gizmogroup_is_visible_in_drawstep(gzgroup, drawstep) || !WM_gizmo_group_type_poll(C, gzgroup->type)) { continue; } @@ -379,7 +415,7 @@ static void gizmomap_prepare_drawing(wmGizmoMap *gzmap, /* Needs to be initialized on first draw. */ /* XXX weak: Gizmo-group may skip refreshing if it's invisible * (map gets untagged nevertheless). */ - if (gzmap->update_flag[drawstep] & GIZMOMAP_IS_REFRESH_CALLBACK) { + if (do_refresh) { /* force refresh again. */ gzgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH; } @@ -396,7 +432,7 @@ static void gizmomap_prepare_drawing(wmGizmoMap *gzmap, } } - gzmap->update_flag[drawstep] &= ~(GIZMOMAP_IS_REFRESH_CALLBACK | GIZMOMAP_IS_PREPARE_DRAW); + gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_PREPARE_DRAW; } /** @@ -716,7 +752,7 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap, /* If it were important we could initialize here, * but this only happens when events are handled before drawing, * just skip to keep code-path for initializing gizmos simple. */ - if ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0) { + if ((gzgroup->hide.any != 0) || ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0)) { continue; } @@ -1126,7 +1162,7 @@ void WM_gizmomap_message_subscribe(bContext *C, struct wmMsgBus *mbus) { for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) { - if ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0 || + if ((gzgroup->hide.any != 0) || (gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0 || !WM_gizmo_group_type_poll(C, gzgroup->type)) { continue; } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 4117c036dcb..c1b56c0b9ae 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2811,6 +2811,12 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers BLI_assert(gzmap != NULL); wmGizmo *gz = wm_gizmomap_highlight_get(gzmap); + /* Special case, needed so postponed refresh can respond to events, + * see #WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK for details. */ + if (WM_gizmomap_tag_refresh_check(gzmap)) { + ED_region_tag_redraw(region); + } + if (region->gizmo_map != handler->gizmo_map) { WM_gizmomap_tag_refresh(handler->gizmo_map); } |