mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
add WCAG 2.1 compliant alternate color
This commit is contained in:
1 parent
6ab283d39c
commit
529fc89fc5
5 files changed
+97
-7
No files matched your search
@@ -202,7 +202,7 @@ public static class GameOptionsMenuPatch
|
||||
{
|
||||
categoryHeaderMasked.Background.color = group.GroupColor;
|
||||
categoryHeaderMasked.Divider.color = group.GroupColor;
|
||||
categoryHeaderMasked.Title.color = group.GroupColor.GetAlternateColor();
|
||||
categoryHeaderMasked.Title.color = group.GroupColor.FindAlternateColor();
|
||||
}
|
||||
|
||||
categoryHeaderMasked.Background.size = new Vector2(
|
||||
@@ -232,10 +232,10 @@ public static class GameOptionsMenuPatch
|
||||
{
|
||||
if (group.GroupColor != Color.clear)
|
||||
{
|
||||
renderer.color = group.GroupColor.GetAlternateColor();
|
||||
renderer.color = group.GroupColor.FindAlternateColor();
|
||||
if (renderer.transform.parent.TryGetComponent<GameOptionButton>(out var btn))
|
||||
{
|
||||
btn.interactableColor = group.GroupColor.GetAlternateColor();
|
||||
btn.interactableColor = group.GroupColor.FindAlternateColor();
|
||||
btn.interactableHoveredColor = Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ public static class LobbyViewPanePatches
|
||||
viewSettingsInfoPanelRoleVariant.chanceTitle.color =
|
||||
viewSettingsInfoPanelRoleVariant.chanceBackground.color =
|
||||
viewSettingsInfoPanelRoleVariant.background.color =
|
||||
customRole.RoleColor.GetAlternateColor();
|
||||
customRole.RoleColor.FindAlternateColor();
|
||||
instance.settingsInfo.Add(viewSettingsInfoPanelRoleVariant.gameObject);
|
||||
num -= 0.664f;
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ public static class RoleSettingMenuPatches
|
||||
}
|
||||
|
||||
__instance.roleHeaderSprite.color = customRole.RoleColor;
|
||||
__instance.roleHeaderText.color = customRole.RoleColor.GetAlternateColor();
|
||||
__instance.roleHeaderText.color = customRole.RoleColor.FindAlternateColor();
|
||||
|
||||
var categoryHeaderMasked = __instance.AdvancedRolesSettings.transform.Find("CategoryHeaderMasked").GetComponent<CategoryHeaderMasked>();
|
||||
|
||||
@@ -465,7 +465,7 @@ public static class RoleSettingMenuPatches
|
||||
__instance.roleChances.Add(roleOptionSetting);
|
||||
|
||||
roleOptionSetting.titleText.transform.localPosition = new Vector3(-0.5376f, -0.2923f, 0f);
|
||||
roleOptionSetting.titleText.color = customRole.RoleColor.GetAlternateColor();
|
||||
roleOptionSetting.titleText.color = customRole.RoleColor.FindAlternateColor();
|
||||
roleOptionSetting.titleText.horizontalAlignment = HorizontalAlignmentOptions.Left;
|
||||
|
||||
if (GameSettingMenuPatches.SelectedMod is null ||
|
||||
@@ -483,7 +483,7 @@ public static class RoleSettingMenuPatches
|
||||
|
||||
var passiveButton = newButton.GetComponent<GameOptionButton>();
|
||||
passiveButton.OnClick = new ButtonClickedEvent();
|
||||
passiveButton.interactableColor = btnRend.color = customRole.RoleColor.GetAlternateColor();
|
||||
passiveButton.interactableColor = btnRend.color = customRole.RoleColor.FindAlternateColor();
|
||||
passiveButton.interactableHoveredColor = Color.white;
|
||||
|
||||
passiveButton.OnClick.AddListener((UnityAction)(() => { ChangeTab(role, __instance); }));
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for the Color struct.
|
||||
/// </summary>
|
||||
public static class ColorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the relative luminance of a color (WCAG 2.1 specification).
|
||||
/// </summary>
|
||||
/// <param name="color">Color to calculate luminance for.</param>
|
||||
/// <returns>Relative luminance value.</returns>
|
||||
public static float GetRelativeLuminance(this Color color)
|
||||
{
|
||||
var r = color.r <= 0.03928f ? color.r / 12.92f : Mathf.Pow((color.r + 0.055f) / 1.055f, 2.4f);
|
||||
var g = color.g <= 0.03928f ? color.g / 12.92f : Mathf.Pow((color.g + 0.055f) / 1.055f, 2.4f);
|
||||
var b = color.b <= 0.03928f ? color.b / 12.92f : Mathf.Pow((color.b + 0.055f) / 1.055f, 2.4f);
|
||||
return 0.2126f * r + 0.7152f * g + 0.0722f * b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the contrast ratio between two colors (WCAG 2.1 specification).
|
||||
/// </summary>
|
||||
/// <param name="colorA">First color.</param>
|
||||
/// <param name="colorB">Second color.</param>
|
||||
/// <returns>Contrast ratio between the two colors.</returns>
|
||||
public static float GetContrastRatio(this Color colorA, Color colorB)
|
||||
{
|
||||
var luminanceA = colorA.GetRelativeLuminance();
|
||||
var luminanceB = colorB.GetRelativeLuminance();
|
||||
return (Mathf.Max(luminanceA, luminanceB) + 0.05f) / (Mathf.Min(luminanceA, luminanceB) + 0.05f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates an accessible alternate color with sufficient contrast.
|
||||
/// </summary>
|
||||
/// <param name="color">Base color.</param>
|
||||
/// <param name="desiredRatio">Target contrast ratio (default 4.5f for AA).</param>
|
||||
/// <returns>Alternate color with sufficient contrast.</returns>
|
||||
public static Color FindAlternateColor(this Color color, float desiredRatio = 4.5f)
|
||||
{
|
||||
var lightColor = FindMinimumContrastColor(color, Color.white, desiredRatio);
|
||||
var darkColor = FindMinimumContrastColor(color, Color.black, desiredRatio);
|
||||
|
||||
return lightColor.GetContrastRatio(color) >= darkColor.GetContrastRatio(color) ? lightColor : darkColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the color with the minimum contrast ratio to the target color.
|
||||
/// </summary>
|
||||
/// <param name="baseColor">The base color to start from.</param>
|
||||
/// <param name="targetColor">The target color to compare against.</param>
|
||||
/// <param name="desiredRatio">The desired contrast ratio.</param>
|
||||
/// <returns>The color with the minimum contrast ratio to the target color.</returns>
|
||||
public static Color FindMinimumContrastColor(Color baseColor, Color targetColor, float desiredRatio)
|
||||
{
|
||||
var baseLuminance = baseColor.GetRelativeLuminance();
|
||||
var isLightening = targetColor == Color.white;
|
||||
|
||||
var targetLuminance = isLightening
|
||||
? desiredRatio * (baseLuminance + 0.05f) - 0.05f
|
||||
: (baseLuminance + 0.05f) / desiredRatio - 0.05f;
|
||||
|
||||
if (isLightening && targetLuminance > 1f) return Color.white;
|
||||
if (!isLightening && targetLuminance < 0f) return Color.black;
|
||||
|
||||
float low = 0f, high = 1f;
|
||||
var bestColor = targetColor;
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var t = (low + high) / 2f;
|
||||
var testColor = Color.Lerp(baseColor, targetColor, t);
|
||||
var testLuminance = testColor.GetRelativeLuminance();
|
||||
|
||||
if ((isLightening && testLuminance >= targetLuminance) || (!isLightening && testLuminance <= targetLuminance))
|
||||
{
|
||||
high = t;
|
||||
bestColor = testColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = t;
|
||||
}
|
||||
}
|
||||
return bestColor;
|
||||
}
|
||||
}
|
||||
@@ -245,6 +245,7 @@ public static class Extensions
|
||||
/// <param name="color">The original color.</param>
|
||||
/// <param name="amount">The amount to darken or lighten the original color by between 0.0 and 1.0.</param>
|
||||
/// <returns>An alternate color that has been darkened or lightened.</returns>
|
||||
[Obsolete("Use FindAlternateColor for WACG compliance.")]
|
||||
public static Color GetAlternateColor(this Color color, float amount = 0.45f)
|
||||
{
|
||||
return color.IsColorDark() ? LightenColor(color, amount) : DarkenColor(color, amount);
|
||||
|
||||
Reference in new issue
Block a user