diff --git a/UI/CMakeLists.txt b/UI/CMakeLists.txt index 8e25b0d6c..b94b03b8d 100644 --- a/UI/CMakeLists.txt +++ b/UI/CMakeLists.txt @@ -247,6 +247,7 @@ target_sources( window-basic-properties.hpp window-basic-settings.cpp window-basic-settings.hpp + window-basic-settings-a11y.cpp window-basic-settings-stream.cpp window-basic-source-select.cpp window-basic-source-select.hpp diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 3403d966c..cf64f902f 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -1060,6 +1060,23 @@ Basic.Settings.Audio.LowLatencyBufferingWarning="Low latency audio buffering mod Basic.Settings.Audio.LowLatencyBufferingWarning.Title="Enable low latency audio buffering mode?" Basic.Settings.Audio.LowLatencyBufferingWarning.Confirm="Are you sure you want to enable low latency audio buffering mode?" +# basic mode 'accessibility' settings +Basic.Settings.Accessibility="Accessibility" +Basic.Settings.Accessibility.ColorOverrides="Use Different Colors" +Basic.Settings.Accessibility.ColorOverrides.SelectRed="Source Border (Selection)" +Basic.Settings.Accessibility.ColorOverrides.SelectGreen="Source Border (Crop)" +Basic.Settings.Accessibility.ColorOverrides.SelectBlue="Source Border (Hover)" +Basic.Settings.Accessibility.ColorOverrides.MixerGreen="Mixer Volume Band (-60 to -20dB)" +Basic.Settings.Accessibility.ColorOverrides.MixerYellow="Mixer Volume Band (-20 to -9dB)" +Basic.Settings.Accessibility.ColorOverrides.MixerRed="Mixer Volume Band (-9 to 0dB)" +Basic.Settings.Accessibility.ColorOverrides.MixerGreenActive="Mixer Volume Band (-60 to -20dB) (active)" +Basic.Settings.Accessibility.ColorOverrides.MixerYellowActive="Mixer Volume Band (-20 to -9dB) (active)" +Basic.Settings.Accessibility.ColorOverrides.MixerRedActive="Mixer Volume Band (-9 to 0dB) (active)" +Basic.Settings.Accessibility.ColorOverrides.Preset="Color Preset" +Basic.Settings.Accessibility.ColorOverrides.Preset.Default="Default" +Basic.Settings.Accessibility.ColorOverrides.Preset.Custom="Custom" +Basic.Settings.Accessibility.ColorOverrides.Preset.ColorBlind1="Color Blind Alternative" + # basic mode 'advanced' settings Basic.Settings.Advanced="Advanced" Basic.Settings.Advanced.General.ConfirmOnExit="Show active outputs warning on exit" diff --git a/UI/data/themes/Dark.qss b/UI/data/themes/Dark.qss index 5c95fa857..51ac1ac65 100644 --- a/UI/data/themes/Dark.qss +++ b/UI/data/themes/Dark.qss @@ -737,6 +737,7 @@ OBSBasicSettings { qproperty-audioIcon: url(./Dark/settings/audio.svg); qproperty-videoIcon: url(./Dark/settings/video.svg); qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); + qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); qproperty-advancedIcon: url(./Dark/settings/advanced.svg); } diff --git a/UI/data/themes/Dark/settings/accessibility.svg b/UI/data/themes/Dark/settings/accessibility.svg new file mode 100644 index 000000000..a630eb49e --- /dev/null +++ b/UI/data/themes/Dark/settings/accessibility.svg @@ -0,0 +1 @@ + diff --git a/UI/data/themes/Yami.qss b/UI/data/themes/Yami.qss index 4ed932da9..b1ba69aaa 100644 --- a/UI/data/themes/Yami.qss +++ b/UI/data/themes/Yami.qss @@ -1022,6 +1022,7 @@ OBSBasicSettings { qproperty-audioIcon: url(./Dark/settings/audio.svg); qproperty-videoIcon: url(./Dark/settings/video.svg); qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); + qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); qproperty-advancedIcon: url(./Dark/settings/advanced.svg); } diff --git a/UI/forms/OBSBasicSettings.ui b/UI/forms/OBSBasicSettings.ui index 46a56d68e..2bc6ef245 100644 --- a/UI/forms/OBSBasicSettings.ui +++ b/UI/forms/OBSBasicSettings.ui @@ -105,6 +105,15 @@ :/settings/images/settings/hotkeys.svg:/settings/images/settings/hotkeys.svg + + + Basic.Settings.Accessibility + + + + :/settings/images/settings/accessibility.svg:/settings/images/settings/accessibility.svg + + Basic.Settings.Advanced @@ -4881,6 +4890,1161 @@ + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + 0 + 0 + 820 + 677 + + + + + 0 + + + 0 + + + 0 + + + 9 + + + + + + + + 0 + 0 + + + + Basic.Settings.Accessibility.ColorOverrides + + + true + + + false + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 2 + + + + + Basic.Settings.Accessibility.ColorOverrides.Preset + + + colorPreset + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.Preset.Default + + + + + Basic.Settings.Accessibility.ColorOverrides.Preset.ColorBlind1 + + + + + Basic.Settings.Accessibility.ColorOverrides.Preset.Custom + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.SelectRed + + + colorSelect1 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.SelectGreen + + + colorSelect2 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.SelectBlue + + + colorSelect3 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.MixerGreen + + + colorSelect4 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.MixerYellow + + + colorSelect5 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.MixerRed + + + colorSelect6 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.MixerGreenActive + + + colorSelect7 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.MixerYellowActive + + + colorSelect8 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Basic.Settings.Accessibility.ColorOverrides.MixerRedActive + + + colorSelect9 + + + + + + + + 0 + 0 + 565 + 22 + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 80 + 22 + + + + + 16777215 + 22 + + + + color here + + + Qt::AlignCenter + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Basic.PropertiesWindow.SelectColor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + + + + + + + + diff --git a/UI/forms/images/settings/accessibility.svg b/UI/forms/images/settings/accessibility.svg new file mode 100644 index 000000000..1587b8933 --- /dev/null +++ b/UI/forms/images/settings/accessibility.svg @@ -0,0 +1 @@ + diff --git a/UI/forms/obs.qrc b/UI/forms/obs.qrc index f3b275ddf..977cfa39d 100644 --- a/UI/forms/obs.qrc +++ b/UI/forms/obs.qrc @@ -70,5 +70,6 @@ images/settings/audio.svg images/settings/general.svg images/settings/hotkeys.svg + images/settings/accessibility.svg diff --git a/UI/volume-control.cpp b/UI/volume-control.cpp index 9102016d9..67e128995 100644 --- a/UI/volume-control.cpp +++ b/UI/volume-control.cpp @@ -336,9 +336,18 @@ VolControl::~VolControl() contextMenu->close(); } +static inline QColor color_from_int(long long val) +{ + QColor color(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, + (val >> 24) & 0xff); + color.setAlpha(255); + + return color; +} + QColor VolumeMeter::getBackgroundNominalColor() const { - return backgroundNominalColor; + return p_backgroundNominalColor; } QColor VolumeMeter::getBackgroundNominalColorDisabled() const @@ -348,7 +357,15 @@ QColor VolumeMeter::getBackgroundNominalColorDisabled() const void VolumeMeter::setBackgroundNominalColor(QColor c) { - backgroundNominalColor = std::move(c); + p_backgroundNominalColor = std::move(c); + + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + backgroundNominalColor = color_from_int(config_get_int( + GetGlobalConfig(), "Accessibility", "MixerGreen")); + } else { + backgroundNominalColor = p_backgroundNominalColor; + } } void VolumeMeter::setBackgroundNominalColorDisabled(QColor c) @@ -358,7 +375,7 @@ void VolumeMeter::setBackgroundNominalColorDisabled(QColor c) QColor VolumeMeter::getBackgroundWarningColor() const { - return backgroundWarningColor; + return p_backgroundWarningColor; } QColor VolumeMeter::getBackgroundWarningColorDisabled() const @@ -368,7 +385,15 @@ QColor VolumeMeter::getBackgroundWarningColorDisabled() const void VolumeMeter::setBackgroundWarningColor(QColor c) { - backgroundWarningColor = std::move(c); + p_backgroundWarningColor = std::move(c); + + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + backgroundWarningColor = color_from_int(config_get_int( + GetGlobalConfig(), "Accessibility", "MixerYellow")); + } else { + backgroundWarningColor = p_backgroundWarningColor; + } } void VolumeMeter::setBackgroundWarningColorDisabled(QColor c) @@ -378,7 +403,7 @@ void VolumeMeter::setBackgroundWarningColorDisabled(QColor c) QColor VolumeMeter::getBackgroundErrorColor() const { - return backgroundErrorColor; + return p_backgroundErrorColor; } QColor VolumeMeter::getBackgroundErrorColorDisabled() const @@ -388,7 +413,15 @@ QColor VolumeMeter::getBackgroundErrorColorDisabled() const void VolumeMeter::setBackgroundErrorColor(QColor c) { - backgroundErrorColor = std::move(c); + p_backgroundErrorColor = std::move(c); + + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + backgroundErrorColor = color_from_int(config_get_int( + GetGlobalConfig(), "Accessibility", "MixerRed")); + } else { + backgroundErrorColor = p_backgroundErrorColor; + } } void VolumeMeter::setBackgroundErrorColorDisabled(QColor c) @@ -398,7 +431,7 @@ void VolumeMeter::setBackgroundErrorColorDisabled(QColor c) QColor VolumeMeter::getForegroundNominalColor() const { - return foregroundNominalColor; + return p_foregroundNominalColor; } QColor VolumeMeter::getForegroundNominalColorDisabled() const @@ -408,7 +441,16 @@ QColor VolumeMeter::getForegroundNominalColorDisabled() const void VolumeMeter::setForegroundNominalColor(QColor c) { - foregroundNominalColor = std::move(c); + p_foregroundNominalColor = std::move(c); + + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + foregroundNominalColor = color_from_int( + config_get_int(GetGlobalConfig(), "Accessibility", + "MixerGreenActive")); + } else { + foregroundNominalColor = p_foregroundNominalColor; + } } void VolumeMeter::setForegroundNominalColorDisabled(QColor c) @@ -418,7 +460,7 @@ void VolumeMeter::setForegroundNominalColorDisabled(QColor c) QColor VolumeMeter::getForegroundWarningColor() const { - return foregroundWarningColor; + return p_foregroundWarningColor; } QColor VolumeMeter::getForegroundWarningColorDisabled() const @@ -428,7 +470,16 @@ QColor VolumeMeter::getForegroundWarningColorDisabled() const void VolumeMeter::setForegroundWarningColor(QColor c) { - foregroundWarningColor = std::move(c); + p_foregroundWarningColor = std::move(c); + + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + foregroundWarningColor = color_from_int( + config_get_int(GetGlobalConfig(), "Accessibility", + "MixerYellowActive")); + } else { + foregroundWarningColor = p_foregroundWarningColor; + } } void VolumeMeter::setForegroundWarningColorDisabled(QColor c) @@ -438,7 +489,7 @@ void VolumeMeter::setForegroundWarningColorDisabled(QColor c) QColor VolumeMeter::getForegroundErrorColor() const { - return foregroundErrorColor; + return p_foregroundErrorColor; } QColor VolumeMeter::getForegroundErrorColorDisabled() const @@ -448,7 +499,15 @@ QColor VolumeMeter::getForegroundErrorColorDisabled() const void VolumeMeter::setForegroundErrorColor(QColor c) { - foregroundErrorColor = std::move(c); + p_foregroundErrorColor = std::move(c); + + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + foregroundErrorColor = color_from_int(config_get_int( + GetGlobalConfig(), "Accessibility", "MixerRedActive")); + } else { + foregroundErrorColor = p_foregroundErrorColor; + } } void VolumeMeter::setForegroundErrorColorDisabled(QColor c) @@ -518,6 +577,20 @@ void VolumeMeter::setMeterFontScaling(qreal v) recalculateLayout = true; } +void VolControl::refreshColors() +{ + volMeter->setBackgroundNominalColor( + volMeter->getBackgroundNominalColor()); + volMeter->setBackgroundWarningColor( + volMeter->getBackgroundWarningColor()); + volMeter->setBackgroundErrorColor(volMeter->getBackgroundErrorColor()); + volMeter->setForegroundNominalColor( + volMeter->getForegroundNominalColor()); + volMeter->setForegroundWarningColor( + volMeter->getForegroundWarningColor()); + volMeter->setForegroundErrorColor(volMeter->getForegroundErrorColor()); +} + qreal VolumeMeter::getMinimumLevel() const { return minimumLevel; diff --git a/UI/volume-control.hpp b/UI/volume-control.hpp index ceceebcbf..45ef608a7 100644 --- a/UI/volume-control.hpp +++ b/UI/volume-control.hpp @@ -168,6 +168,13 @@ private: qreal peakHoldDuration; qreal inputPeakHoldDuration; + QColor p_backgroundNominalColor; + QColor p_backgroundWarningColor; + QColor p_backgroundErrorColor; + QColor p_foregroundNominalColor; + QColor p_foregroundWarningColor; + QColor p_foregroundErrorColor; + uint64_t lastRedrawTime = 0; int channels = 0; bool clipping = false; @@ -322,4 +329,6 @@ public: void EnableSlider(bool enable); inline void SetContextMenu(QMenu *cm) { contextMenu = cm; } + + void refreshColors(); }; diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index e9cf9075c..e66ca53e7 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -623,6 +623,13 @@ void OBSBasic::ClearVolumeControls() volumes.clear(); } +void OBSBasic::RefreshVolumeColors() +{ + for (VolControl *vol : volumes) { + vol->refreshColors(); + } +} + obs_data_array_t *OBSBasic::SaveSceneListOrder() { obs_data_array_t *sceneOrder = obs_data_array_create(); @@ -10099,3 +10106,42 @@ void OBSBasic::SetDisplayAffinity(QWindow *window) UNUSED_PARAMETER(hideFromCapture); #endif } + +static inline QColor color_from_int(long long val) +{ + return QColor(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, + (val >> 24) & 0xff); +} + +QColor OBSBasic::GetSelectionColor() const +{ + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + return color_from_int(config_get_int( + GetGlobalConfig(), "Accessibility", "SelectRed")); + } else { + return QColor::fromRgb(255, 0, 0); + } +} + +QColor OBSBasic::GetCropColor() const +{ + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + return color_from_int(config_get_int( + GetGlobalConfig(), "Accessibility", "SelectGreen")); + } else { + return QColor::fromRgb(0, 255, 0); + } +} + +QColor OBSBasic::GetHoverColor() const +{ + if (config_get_bool(GetGlobalConfig(), "Accessibility", + "OverrideColors")) { + return color_from_int(config_get_int( + GetGlobalConfig(), "Accessibility", "SelectBlue")); + } else { + return QColor::fromRgb(0, 127, 255); + } +} diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 3dee95a4a..3e9695f2a 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -624,6 +624,14 @@ private: void CenterSelectedSceneItems(const CenterType ¢erType); void ShowMissingFilesDialog(obs_missing_files_t *files); + QColor selectionColor; + QColor cropColor; + QColor hoverColor; + + QColor GetSelectionColor() const; + QColor GetCropColor() const; + QColor GetHoverColor() const; + public slots: void DeferSaveBegin(); void DeferSaveEnd(); @@ -866,6 +874,8 @@ public: void AddVCamButton(); void ResetOutputs(); + void RefreshVolumeColors(); + void ResetAudioDevice(const char *sourceId, const char *deviceId, const char *deviceDesc, int channel); diff --git a/UI/window-basic-preview.cpp b/UI/window-basic-preview.cpp index adfb8a44b..ee58d10f5 100644 --- a/UI/window-basic-preview.cpp +++ b/UI/window-basic-preview.cpp @@ -1829,13 +1829,22 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene, {{{1.f, 1.f, 0.f}}}, }; + main->GetCameraIcon(); + + QColor selColor = main->GetSelectionColor(); + QColor cropColor = main->GetCropColor(); + QColor hoverColor = main->GetHoverColor(); + vec4 red; vec4 green; vec4 blue; - vec4_set(&red, 1.0f, 0.0f, 0.0f, 1.0f); - vec4_set(&green, 0.0f, 1.0f, 0.0f, 1.0f); - vec4_set(&blue, 0.0f, 0.5f, 1.0f, 1.0f); + vec4_set(&red, selColor.redF(), selColor.greenF(), selColor.blueF(), + 1.0f); + vec4_set(&green, cropColor.redF(), cropColor.greenF(), + cropColor.blueF(), 1.0f); + vec4_set(&blue, hoverColor.redF(), hoverColor.greenF(), + hoverColor.blueF(), 1.0f); bool visible = std::all_of( std::begin(bounds), std::end(bounds), [&](const vec3 &b) { @@ -1869,6 +1878,8 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene, gs_effect_t *eff = gs_get_effect(); gs_eparam_t *colParam = gs_effect_get_param_by_name(eff, "color"); + gs_effect_set_vec4(colParam, &red); + if (info.bounds_type == OBS_BOUNDS_NONE && crop_enabled(&crop)) { #define DRAW_SIDE(side, x1, y1, x2, y2) \ if (hovered && !selected) { \ @@ -2003,10 +2014,6 @@ void OBSBasicPreview::DrawSceneEditing() gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID); gs_technique_t *tech = gs_effect_get_technique(solid, "Solid"); - vec4 color; - vec4_set(&color, 1.0f, 0.0f, 0.0f, 1.0f); - gs_effect_set_vec4(gs_effect_get_param_by_name(solid, "color"), &color); - gs_technique_begin(tech); gs_technique_begin_pass(tech, 0); diff --git a/UI/window-basic-settings-a11y.cpp b/UI/window-basic-settings-a11y.cpp new file mode 100644 index 000000000..136e36ee5 --- /dev/null +++ b/UI/window-basic-settings-a11y.cpp @@ -0,0 +1,398 @@ +#include "window-basic-settings.hpp" +#include "window-basic-main.hpp" +#include "obs-frontend-api.h" +#include "obs-app.hpp" +#include "qt-wrappers.hpp" +#include + +#define I18nStr(str) QTStr(str).toStdString().c_str() + +enum ColorPreset { + COLOR_PRESET_DEFAULT, + COLOR_PRESET_COLOR_BLIND_1, + COLOR_PRESET_CUSTOM = 99, +}; + +static inline bool WidgetChanged(QWidget *widget) +{ + return widget->property("changed").toBool(); +} + +static inline QColor color_from_int(long long val) +{ + return QColor(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, + (val >> 24) & 0xff); +} + +static inline long long color_to_int(QColor color) +{ + auto shift = [&](unsigned val, int shift) { + return ((val & 0xff) << shift); + }; + + return shift(color.red(), 0) | shift(color.green(), 8) | + shift(color.blue(), 16) | shift(color.alpha(), 24); +} + +QColor OBSBasicSettings::GetColor(uint32_t colorVal, QString label) +{ + QColorDialog::ColorDialogOptions options; + +#ifndef _WIN32 + options |= QColorDialog::DontUseNativeDialog; +#endif + + QColor color = color_from_int(colorVal); + + return QColorDialog::getColor(color, this, label, options); +} + +void OBSBasicSettings::LoadA11ySettings(bool presetChange) +{ + config_t *config = GetGlobalConfig(); + + if (!presetChange) { + preset = config_get_int(config, "Accessibility", "ColorPreset"); + + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(std::min( + preset, (uint32_t)ui->colorPreset->count() - 1)); + ui->colorPreset->blockSignals(block); + + bool checked = config_get_bool(config, "Accessibility", + "OverrideColors"); + + ui->colorsGroupBox->setChecked(checked); + } + + if (preset == COLOR_PRESET_DEFAULT) { + ResetDefaultColors(); + SetDefaultColors(); + } else if (preset == COLOR_PRESET_COLOR_BLIND_1) { + ResetDefaultColors(); + + mixerGreenActive = 0x742E94; + mixerGreen = 0x4A1A60; + mixerYellowActive = 0x3349F9; + mixerYellow = 0x1F2C97; + mixerRedActive = 0xBEAC63; + mixerRed = 0x675B28; + + selectRed = 0x3349F9; + selectGreen = 0xFF56C9; + selectBlue = 0xB09B44; + + SetDefaultColors(); + } else if (preset == COLOR_PRESET_CUSTOM) { + SetDefaultColors(); + + selectRed = + config_get_int(config, "Accessibility", "SelectRed"); + selectGreen = + config_get_int(config, "Accessibility", "SelectGreen"); + selectBlue = + config_get_int(config, "Accessibility", "SelectBlue"); + + mixerGreen = + config_get_int(config, "Accessibility", "MixerGreen"); + mixerYellow = + config_get_int(config, "Accessibility", "MixerYellow"); + mixerRed = config_get_int(config, "Accessibility", "MixerRed"); + + mixerGreenActive = config_get_int(config, "Accessibility", + "MixerGreenActive"); + mixerYellowActive = config_get_int(config, "Accessibility", + "MixerYellowActive"); + mixerRedActive = config_get_int(config, "Accessibility", + "MixerRedActive"); + } + + UpdateA11yColors(); +} + +void OBSBasicSettings::SaveA11ySettings() +{ + config_t *config = GetGlobalConfig(); + + config_set_bool(config, "Accessibility", "OverrideColors", + ui->colorsGroupBox->isChecked()); + config_set_int(config, "Accessibility", "ColorPreset", preset); + + config_set_int(config, "Accessibility", "SelectRed", selectRed); + config_set_int(config, "Accessibility", "SelectGreen", selectGreen); + config_set_int(config, "Accessibility", "SelectBlue", selectBlue); + config_set_int(config, "Accessibility", "MixerGreen", mixerGreen); + config_set_int(config, "Accessibility", "MixerYellow", mixerYellow); + config_set_int(config, "Accessibility", "MixerRed", mixerRed); + config_set_int(config, "Accessibility", "MixerGreenActive", + mixerGreenActive); + config_set_int(config, "Accessibility", "MixerYellowActive", + mixerYellowActive); + config_set_int(config, "Accessibility", "MixerRedActive", + mixerRedActive); + + main->RefreshVolumeColors(); +} + +#define SetStyle(label, colorVal) \ + color = color_from_int(colorVal); \ + color.setAlpha(255); \ + palette = QPalette(color); \ + label->setFrameStyle(QFrame::Sunken | QFrame::Panel); \ + label->setText(color.name(QColor::HexRgb)); \ + label->setPalette(palette); \ + label->setStyleSheet(QString("background-color: %1; color: %2;") \ + .arg(palette.color(QPalette::Window) \ + .name(QColor::HexRgb)) \ + .arg(palette.color(QPalette::WindowText) \ + .name(QColor::HexRgb))); \ + label->setAutoFillBackground(true); \ + label->setAlignment(Qt::AlignCenter); + +void OBSBasicSettings::UpdateA11yColors() +{ + QPalette palette; + QColor color; + + SetStyle(ui->color1, selectRed); + SetStyle(ui->color2, selectGreen); + SetStyle(ui->color3, selectBlue); + SetStyle(ui->color4, mixerGreen); + SetStyle(ui->color5, mixerYellow); + SetStyle(ui->color6, mixerRed); + SetStyle(ui->color7, mixerGreenActive); + SetStyle(ui->color8, mixerYellowActive); + SetStyle(ui->color9, mixerRedActive); +} + +void OBSBasicSettings::SetDefaultColors() +{ + config_t *config = GetGlobalConfig(); + config_set_default_int(config, "Accessibility", "SelectRed", selectRed); + config_set_default_int(config, "Accessibility", "SelectGreen", + selectGreen); + config_set_default_int(config, "Accessibility", "SelectBlue", + selectBlue); + + config_set_default_int(config, "Accessibility", "MixerGreen", + mixerGreen); + config_set_default_int(config, "Accessibility", "MixerYellow", + mixerYellow); + config_set_default_int(config, "Accessibility", "MixerRed", mixerRed); + + config_set_default_int(config, "Accessibility", "MixerGreenActive", + mixerGreenActive); + config_set_default_int(config, "Accessibility", "MixerYellowActive", + mixerYellowActive); + config_set_default_int(config, "Accessibility", "MixerRedActive", + mixerRedActive); +} + +void OBSBasicSettings::ResetDefaultColors() +{ + selectRed = 0x0000FF; + selectGreen = 0x00FF00; + selectBlue = 0xFF7F00; + mixerGreen = 0x267f26; + mixerYellow = 0x267f7f; + mixerRed = 0x26267f; + mixerGreenActive = 0x4cff4c; + mixerYellowActive = 0x4cffff; + mixerRedActive = 0x4c4cff; +} + +void OBSBasicSettings::on_colorPreset_currentIndexChanged(int idx) +{ + preset = idx == ui->colorPreset->count() - 1 ? COLOR_PRESET_CUSTOM + : idx; + LoadA11ySettings(true); +} + +void OBSBasicSettings::on_choose1_clicked() +{ + QColor color = GetColor( + selectRed, + QTStr("Basic.Settings.Accessibility.ColorOverrides.SelectRed")); + + if (!color.isValid()) + return; + + selectRed = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} + +void OBSBasicSettings::on_choose2_clicked() +{ + QColor color = GetColor( + selectGreen, + QTStr("Basic.Settings.Accessibility.ColorOverrides.SelectGreen")); + + if (!color.isValid()) + return; + + selectGreen = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} + +void OBSBasicSettings::on_choose3_clicked() +{ + QColor color = GetColor( + selectBlue, + QTStr("Basic.Settings.Accessibility.ColorOverrides.SelectBlue")); + + if (!color.isValid()) + return; + + selectBlue = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} + +void OBSBasicSettings::on_choose4_clicked() +{ + QColor color = GetColor( + mixerGreen, + QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerGreen")); + + if (!color.isValid()) + return; + + mixerGreen = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} + +void OBSBasicSettings::on_choose5_clicked() +{ + QColor color = GetColor( + mixerYellow, + QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerYellow")); + + if (!color.isValid()) + return; + + mixerYellow = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} + +void OBSBasicSettings::on_choose6_clicked() +{ + QColor color = GetColor( + mixerRed, + QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerRed")); + + if (!color.isValid()) + return; + + mixerRed = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} + +void OBSBasicSettings::on_choose7_clicked() +{ + QColor color = GetColor( + mixerGreenActive, + QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerGreenActive")); + + if (!color.isValid()) + return; + + mixerGreenActive = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} + +void OBSBasicSettings::on_choose8_clicked() +{ + QColor color = GetColor( + mixerYellowActive, + QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerYellowActive")); + + if (!color.isValid()) + return; + + mixerYellowActive = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} + +void OBSBasicSettings::on_choose9_clicked() +{ + QColor color = GetColor( + mixerRedActive, + QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerRedActive")); + + if (!color.isValid()) + return; + + mixerRedActive = color_to_int(color); + + preset = COLOR_PRESET_CUSTOM; + bool block = ui->colorPreset->blockSignals(true); + ui->colorPreset->setCurrentIndex(ui->colorPreset->count() - 1); + ui->colorPreset->blockSignals(block); + + A11yChanged(); + + UpdateA11yColors(); +} diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index ee59fd5c6..bc75e9142 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -350,6 +350,7 @@ void OBSBasicSettings::HookWidget(QWidget *widget, const char *signal, #define VIDEO_RESTART SLOT(VideoChangedRestart()) #define VIDEO_RES SLOT(VideoChangedResolution()) #define VIDEO_CHANGED SLOT(VideoChanged()) +#define A11Y_CHANGED SLOT(A11yChanged()) #define ADV_CHANGED SLOT(AdvancedChanged()) #define ADV_RESTART SLOT(AdvancedChangedRestart()) /* clang-format on */ @@ -528,6 +529,8 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent) HookWidget(ui->fpsInteger, SCROLL_CHANGED, VIDEO_CHANGED); HookWidget(ui->fpsNumerator, SCROLL_CHANGED, VIDEO_CHANGED); HookWidget(ui->fpsDenominator, SCROLL_CHANGED, VIDEO_CHANGED); + HookWidget(ui->colorsGroupBox, CHECK_CHANGED, A11Y_CHANGED); + HookWidget(ui->colorPreset, COMBO_CHANGED, A11Y_CHANGED); HookWidget(ui->renderer, COMBO_CHANGED, ADV_RESTART); HookWidget(ui->adapter, COMBO_CHANGED, ADV_RESTART); HookWidget(ui->colorFormat, COMBO_CHANGED, ADV_CHANGED); @@ -3026,6 +3029,8 @@ void OBSBasicSettings::LoadSettings(bool changedOnly) LoadVideoSettings(); if (!changedOnly || hotkeysChanged) LoadHotkeySettings(); + if (!changedOnly || a11yChanged) + LoadA11ySettings(); if (!changedOnly || advancedChanged) LoadAdvancedSettings(); } @@ -3806,6 +3811,8 @@ void OBSBasicSettings::SaveSettings() SaveVideoSettings(); if (hotkeysChanged) SaveHotkeySettings(); + if (a11yChanged) + SaveA11ySettings(); if (advancedChanged) SaveAdvancedSettings(); @@ -3830,6 +3837,8 @@ void OBSBasicSettings::SaveSettings() AddChangedVal(changed, "video"); if (hotkeysChanged) AddChangedVal(changed, "hotkeys"); + if (a11yChanged) + AddChangedVal(changed, "a11y"); if (advancedChanged) AddChangedVal(changed, "advanced"); @@ -4544,6 +4553,15 @@ void OBSBasicSettings::ReloadHotkeys(obs_hotkey_id ignoreKey) LoadHotkeySettings(ignoreKey); } +void OBSBasicSettings::A11yChanged() +{ + if (!loading) { + a11yChanged = true; + sender()->setProperty("changed", QVariant(true)); + EnableApplyButton(true); + } +} + void OBSBasicSettings::AdvancedChanged() { if (!loading) { @@ -5278,6 +5296,11 @@ QIcon OBSBasicSettings::GetHotkeysIcon() const return hotkeysIcon; } +QIcon OBSBasicSettings::GetAccessibilityIcon() const +{ + return accessibilityIcon; +} + QIcon OBSBasicSettings::GetAdvancedIcon() const { return advancedIcon; @@ -5313,11 +5336,16 @@ void OBSBasicSettings::SetHotkeysIcon(const QIcon &icon) ui->listWidget->item(5)->setIcon(icon); } -void OBSBasicSettings::SetAdvancedIcon(const QIcon &icon) +void OBSBasicSettings::SetAccessibilityIcon(const QIcon &icon) { ui->listWidget->item(6)->setIcon(icon); } +void OBSBasicSettings::SetAdvancedIcon(const QIcon &icon) +{ + ui->listWidget->item(7)->setIcon(icon); +} + int OBSBasicSettings::CurrentFLVTrack() { if (ui->flvTrack1->isChecked()) diff --git a/UI/window-basic-settings.hpp b/UI/window-basic-settings.hpp index c511c719b..9a96418d3 100644 --- a/UI/window-basic-settings.hpp +++ b/UI/window-basic-settings.hpp @@ -97,6 +97,8 @@ class OBSBasicSettings : public QDialog { DESIGNABLE true) Q_PROPERTY(QIcon hotkeysIcon READ GetHotkeysIcon WRITE SetHotkeysIcon DESIGNABLE true) + Q_PROPERTY(QIcon accessibilityIcon READ GetAccessibilityIcon WRITE + SetAccessibilityIcon DESIGNABLE true) Q_PROPERTY(QIcon advancedIcon READ GetAdvancedIcon WRITE SetAdvancedIcon DESIGNABLE true) @@ -113,6 +115,7 @@ private: bool audioChanged = false; bool videoChanged = false; bool hotkeysChanged = false; + bool a11yChanged = false; bool advancedChanged = false; int pageIndex = 0; bool loading = true; @@ -194,7 +197,7 @@ private: { return generalChanged || outputsChanged || stream1Changed || audioChanged || videoChanged || advancedChanged || - hotkeysChanged; + hotkeysChanged || a11yChanged; } inline void EnableApplyButton(bool en) @@ -210,6 +213,7 @@ private: audioChanged = false; videoChanged = false; hotkeysChanged = false; + a11yChanged = false; advancedChanged = false; EnableApplyButton(false); } @@ -240,6 +244,7 @@ private: void LoadVideoSettings(); void LoadHotkeySettings(obs_hotkey_id ignoreKey = OBS_INVALID_HOTKEY_ID); + void LoadA11ySettings(bool presetChange = false); void LoadAdvancedSettings(); void LoadSettings(bool changedOnly); @@ -306,12 +311,29 @@ private: void LoadResolutionLists(); void LoadFPSData(); + /* a11y */ + void UpdateA11yColors(); + void SetDefaultColors(); + void ResetDefaultColors(); + QColor GetColor(uint32_t colorVal, QString label); + uint32_t preset = 0; + uint32_t selectRed = 0x0000FF; + uint32_t selectGreen = 0x00FF00; + uint32_t selectBlue = 0xFF7F00; + uint32_t mixerGreen = 0x267f26; + uint32_t mixerYellow = 0x267f7f; + uint32_t mixerRed = 0x26267f; + uint32_t mixerGreenActive = 0x4cff4c; + uint32_t mixerYellowActive = 0x4cffff; + uint32_t mixerRedActive = 0x4c4cff; + void SaveGeneralSettings(); void SaveStream1Settings(); void SaveOutputSettings(); void SaveAudioSettings(); void SaveVideoSettings(); void SaveHotkeySettings(); + void SaveA11ySettings(); void SaveAdvancedSettings(); void SaveSettings(); @@ -334,6 +356,7 @@ private: QIcon audioIcon; QIcon videoIcon; QIcon hotkeysIcon; + QIcon accessibilityIcon; QIcon advancedIcon; QIcon GetGeneralIcon() const; @@ -342,6 +365,7 @@ private: QIcon GetAudioIcon() const; QIcon GetVideoIcon() const; QIcon GetHotkeysIcon() const; + QIcon GetAccessibilityIcon() const; QIcon GetAdvancedIcon() const; int CurrentFLVTrack(); @@ -380,6 +404,17 @@ private slots: void on_disableOSXVSync_clicked(); + void on_choose1_clicked(); + void on_choose2_clicked(); + void on_choose3_clicked(); + void on_choose4_clicked(); + void on_choose5_clicked(); + void on_choose6_clicked(); + void on_choose7_clicked(); + void on_choose8_clicked(); + void on_choose9_clicked(); + void on_colorPreset_currentIndexChanged(int idx); + void GeneralChanged(); void HideOBSWindowWarning(int state); void AudioChanged(); @@ -397,6 +432,7 @@ private slots: void HotkeysChanged(); bool ScanDuplicateHotkeys(QFormLayout *layout); void ReloadHotkeys(obs_hotkey_id ignoreKey = OBS_INVALID_HOTKEY_ID); + void A11yChanged(); void AdvancedChanged(); void AdvancedChangedRestart(); @@ -426,6 +462,7 @@ private slots: void SetAudioIcon(const QIcon &icon); void SetVideoIcon(const QIcon &icon); void SetHotkeysIcon(const QIcon &icon); + void SetAccessibilityIcon(const QIcon &icon); void SetAdvancedIcon(const QIcon &icon); void UseStreamKeyAdvClicked();