wayvr/wgui/src/color.rs

195 lines
4.3 KiB
Rust

use crate::{drawing, palette::WguiColorPalette};
use strum::{EnumCount, EnumString};
// Primary: button color
// OnPrimary: text color placed on the Primary-colored button
#[derive(Debug, Copy, Clone, EnumCount, EnumString)]
#[repr(usize)]
#[strum(serialize_all = "snake_case")]
pub enum WguiColorName {
Primary,
OnPrimary,
Secondary,
OnSecondary,
Tertiary,
OnTertiary,
Danger,
OnDanger,
Background,
OnBackground,
BackgroundVariant,
OnBackgroundVariant,
BackgroundContrast,
OnBackgroundContrast,
Outline,
Shadow,
Highlight,
}
#[derive(Clone, Copy, Debug)]
pub struct WguiNamedColor {
name: WguiColorName,
rgb_multiplier: f32,
rgb_addition: f32,
alpha: f32,
}
#[derive(Clone, Copy, Debug)]
pub enum WguiColor {
Raw(drawing::Color),
Named(WguiNamedColor),
}
impl WguiColor {
pub fn resolve(&self, palette: &WguiColorPalette) -> drawing::Color {
match &self {
WguiColor::Raw(color) => *color,
WguiColor::Named(color) => color.resolve(palette),
}
}
#[must_use]
pub const fn mult_rgb(&self, mult: f32) -> WguiColor {
match self {
WguiColor::Raw(color) => WguiColor::Raw(color.mult_rgb(mult)),
WguiColor::Named(color) => WguiColor::Named(WguiNamedColor {
name: color.name,
rgb_multiplier: color.rgb_multiplier * mult,
rgb_addition: color.rgb_addition,
alpha: color.alpha,
}),
}
}
#[must_use]
pub const fn add_rgb(&self, addition: f32) -> WguiColor {
match self {
WguiColor::Raw(color) => WguiColor::Raw(color.add_rgb(addition)),
WguiColor::Named(color) => WguiColor::Named(WguiNamedColor {
name: color.name,
rgb_multiplier: color.rgb_multiplier,
rgb_addition: color.rgb_addition + addition,
alpha: color.alpha,
}),
}
}
#[must_use]
pub const fn add_alpha(&self, alpha: f32) -> WguiColor {
match self {
WguiColor::Raw(color) => WguiColor::Raw(drawing::Color {
r: color.r,
g: color.g,
b: color.b,
a: color.a + alpha,
}),
WguiColor::Named(color) => WguiColor::Named(WguiNamedColor {
name: color.name,
rgb_multiplier: color.rgb_multiplier,
rgb_addition: color.rgb_addition,
alpha: color.alpha + alpha,
}),
}
}
#[must_use]
pub const fn with_alpha(&self, alpha: f32) -> WguiColor {
match self {
WguiColor::Raw(color) => WguiColor::Raw(color.with_alpha(alpha)),
WguiColor::Named(color) => WguiColor::Named(WguiNamedColor {
name: color.name,
rgb_multiplier: color.rgb_multiplier,
rgb_addition: color.rgb_addition,
alpha,
}),
}
}
// returns named colors if val is 0 or 1, raw otherwise
#[must_use]
pub fn lerp(&self, palette: &WguiColorPalette, other: &WguiColor, val: f32) -> WguiColor {
if val <= 0.0 {
*self
} else if val >= 1.0 {
*other
} else {
let c1 = self.resolve(palette);
let c2 = other.resolve(palette);
c1.lerp(&c2, val).into()
}
}
pub fn on_color(&self) -> Option<Self> {
if let Self::Named(name) = self {
name.name.on_color().map(|x| x.into())
} else {
None
}
}
}
impl WguiColorName {
pub fn on_color(&self) -> Option<Self> {
match self {
Self::Primary => Some(Self::OnPrimary),
Self::Secondary => Some(Self::OnSecondary),
Self::Tertiary => Some(Self::OnTertiary),
Self::Danger => Some(Self::OnDanger),
Self::Background => Some(Self::OnBackground),
Self::BackgroundVariant => Some(Self::OnBackgroundVariant),
Self::BackgroundContrast => Some(Self::OnBackgroundContrast),
_ => None,
}
}
pub const fn to_wgui_color(&self) -> WguiColor {
WguiColor::Named(WguiNamedColor {
name: *self,
alpha: 1.0,
rgb_multiplier: 1.0,
rgb_addition: 0.0,
})
}
}
impl From<WguiColorName> for WguiColor {
fn from(name: WguiColorName) -> Self {
name.to_wgui_color()
}
}
impl From<drawing::Color> for WguiColor {
fn from(color: drawing::Color) -> Self {
WguiColor::Raw(color)
}
}
impl Default for WguiColor {
fn default() -> Self {
Self::Raw(Default::default())
}
}
impl WguiNamedColor {
pub fn resolve(&self, palette: &WguiColorPalette) -> drawing::Color {
let mut color = palette[self.name];
if self.alpha != 1.0 {
color.a *= self.alpha;
}
if self.rgb_multiplier != 1.0 {
color.r *= self.rgb_multiplier;
color.g *= self.rgb_multiplier;
color.b *= self.rgb_multiplier;
}
if self.rgb_addition != 0.0 {
color.r += self.rgb_addition;
color.g += self.rgb_addition;
color.b += self.rgb_addition;
}
color
}
}