From eae4585177bda9f68d071e9f73ef5209b0b15be0 Mon Sep 17 00:00:00 2001 From: Pablo Vazquez Date: Fri, 5 Sep 2025 21:12:52 +0200 Subject: [PATCH] UI: Accessibility: Reduce Motion Add "Reduce Motion" option to a new `Accessibility` panel under Preferences, User Interface. "Reduce Motion" avoids non-essential animation effects, especially useful for those experiencing motion sickness/vertigo. It affects: * Region open/close. * Pie menus animation. * Smooth views. This panel in the future could host common accessibility settings such as "Increase Contrast" or font size and weight controls that currently are part of themes. See PR for details and screenshots. Co-authored-by: Harley Acheson Pull Request: https://projects.blender.org/blender/blender/pulls/140873 --- scripts/startup/bl_ui/space_userpref.py | 14 ++++++++++++++ .../blenloader/intern/versioning_userdef.cc | 2 +- .../editors/interface/interface_handlers.cc | 4 +++- source/blender/editors/screen/area.cc | 2 +- source/blender/makesdna/DNA_userdef_types.h | 2 +- source/blender/makesrna/intern/rna_space.cc | 2 +- source/blender/makesrna/intern/rna_userdef.cc | 7 +++++++ .../blender/windowmanager/intern/wm_operators.cc | 2 +- 8 files changed, 29 insertions(+), 6 deletions(-) diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index 314509ba593..729498c0c8d 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -270,6 +270,19 @@ class USERPREF_PT_interface_translation(InterfacePanel, CenterAlignMixIn, Panel) col.prop(view, "use_translate_new_dataname", text="New Data") +class USERPREF_PT_interface_accessibility(InterfacePanel, CenterAlignMixIn, Panel): + bl_label = "Accessibility" + bl_options = {'DEFAULT_CLOSED'} + + def draw_centered(self, context, layout): + prefs = context.preferences + view = prefs.view + + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + + flow.prop(view, "use_reduce_motion") + + class USERPREF_PT_interface_editors(InterfacePanel, CenterAlignMixIn, Panel): bl_label = "Editors" @@ -2954,6 +2967,7 @@ classes = ( USERPREF_PT_interface_temporary_windows, USERPREF_PT_interface_statusbar, USERPREF_PT_interface_translation, + USERPREF_PT_interface_accessibility, USERPREF_PT_interface_text, USERPREF_PT_interface_menus, USERPREF_PT_interface_menus_mouse_over, diff --git a/source/blender/blenloader/intern/versioning_userdef.cc b/source/blender/blenloader/intern/versioning_userdef.cc index 5c166c566b0..4b39bcb7153 100644 --- a/source/blender/blenloader/intern/versioning_userdef.cc +++ b/source/blender/blenloader/intern/versioning_userdef.cc @@ -1146,7 +1146,7 @@ void blo_do_versions_userdef(UserDef *userdef) } if (!USER_VERSION_ATLEAST(280, 44)) { - userdef->uiflag &= ~(USER_NO_MULTITOUCH_GESTURES | USER_UIFLAG_UNUSED_1); + userdef->uiflag &= ~USER_NO_MULTITOUCH_GESTURES; userdef->uiflag2 &= ~USER_UIFLAG2_UNUSED_0; userdef->gp_settings &= ~GP_PAINT_UNUSED_0; } diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index 518b06e9af2..a128fc0f7ca 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -11558,7 +11558,9 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle /* handle animation */ if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) { - const double final_time = 0.01 * U.pie_animation_timeout; + const double final_time = (U.uiflag & USER_REDUCE_MOTION) ? + 0.0f : + 0.01 * U.pie_animation_timeout; float fac = duration / final_time; const float pie_radius = U.pie_menu_radius * UI_SCALE_FAC; diff --git a/source/blender/editors/screen/area.cc b/source/blender/editors/screen/area.cc index 40910c175ff..0767a5d30c2 100644 --- a/source/blender/editors/screen/area.cc +++ b/source/blender/editors/screen/area.cc @@ -2360,7 +2360,7 @@ void region_toggle_hidden(bContext *C, ARegion *region, const bool do_fade) region->flag ^= RGN_FLAG_HIDDEN; - if (do_fade && region->overlap) { + if (do_fade && region->overlap && !(U.uiflag & USER_REDUCE_MOTION)) { /* starts a timer, and in end calls the stuff below itself (region_sblend_invoke()) */ ED_region_visibility_change_update_animated(C, area, region); } diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index eccbd221ce8..bc07eb113cf 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -763,7 +763,7 @@ typedef enum eWalkNavigation_Flag { /** #UserDef.uiflag */ typedef enum eUserpref_UI_Flag { USER_NO_MULTITOUCH_GESTURES = (1 << 0), - USER_UIFLAG_UNUSED_1 = (1 << 1), /* cleared */ + USER_REDUCE_MOTION = (1 << 1), USER_WHEELZOOMDIR = (1 << 2), USER_FILTERFILEEXTS = (1 << 3), USER_DRAWVIEWINFO = (1 << 4), diff --git a/source/blender/makesrna/intern/rna_space.cc b/source/blender/makesrna/intern/rna_space.cc index ba6153a0652..98a9cf756c4 100644 --- a/source/blender/makesrna/intern/rna_space.cc +++ b/source/blender/makesrna/intern/rna_space.cc @@ -769,7 +769,7 @@ static void rna_Space_bool_from_region_flag_update_by_type(bContext *C, if (region) { if (region_flag == RGN_FLAG_HIDDEN) { /* Only support animation when the area is in the current context. */ - if (region->overlap && (area == CTX_wm_area(C))) { + if (region->overlap && (area == CTX_wm_area(C)) && !(U.uiflag & USER_REDUCE_MOTION)) { ED_region_visibility_change_update_animated(C, area, region); } else { diff --git a/source/blender/makesrna/intern/rna_userdef.cc b/source/blender/makesrna/intern/rna_userdef.cc index c433765ec48..3042c475f07 100644 --- a/source/blender/makesrna/intern/rna_userdef.cc +++ b/source/blender/makesrna/intern/rna_userdef.cc @@ -5375,6 +5375,13 @@ static void rna_def_userdef_view(BlenderRNA *brna) prop, nullptr, "statusbar_flag", STATUSBAR_SHOW_EXTENSIONS_UPDATES); RNA_def_property_ui_text(prop, "Extensions Updates", "Show Extensions Update Count"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO, "rna_userdef_update"); + + /* Accessibility. */ + prop = RNA_def_property(srna, "use_reduce_motion", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "uiflag", USER_REDUCE_MOTION); + RNA_def_property_ui_text( + prop, "Reduce Motion", "Avoid animations and other motion effects in the interface"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_edit(BlenderRNA *brna) diff --git a/source/blender/windowmanager/intern/wm_operators.cc b/source/blender/windowmanager/intern/wm_operators.cc index 1046a74b24f..966acb913ab 100644 --- a/source/blender/windowmanager/intern/wm_operators.cc +++ b/source/blender/windowmanager/intern/wm_operators.cc @@ -1080,7 +1080,7 @@ void WM_operator_view3d_unit_defaults(bContext *C, wmOperator *op) int WM_operator_smooth_viewtx_get(const wmOperator *op) { - return (op->flag & OP_IS_INVOKE) ? U.smooth_viewtx : 0; + return (op->flag & OP_IS_INVOKE && !(U.uiflag & USER_REDUCE_MOTION)) ? U.smooth_viewtx : 0; } wmOperatorStatus WM_menu_invoke_ex(bContext *C,