From 7184a9f21f6904971415619f68a4ca67f22b3573 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Sun, 14 Apr 2024 17:48:44 +0900 Subject: [PATCH] feat: canvas alpha --- src/gui/mod.rs | 68 +++++++++++++++++++++++++--------------- src/gui/modular/label.rs | 14 ++++----- src/gui/modular/mod.rs | 29 +++++++++-------- 3 files changed, 64 insertions(+), 47 deletions(-) diff --git a/src/gui/mod.rs b/src/gui/mod.rs index 447596a..ac9ee3a 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use anyhow::bail; -use glam::{Vec2, Vec3, Vec4}; +use glam::{Vec2, Vec4}; use vulkano::{ command_buffer::CommandBufferUsage, format::Format, @@ -19,6 +19,8 @@ use crate::{ state::AppState, }; +use self::modular::GuiColor; + pub mod font; pub mod modular; @@ -32,14 +34,33 @@ struct Rect { } // Parses a color from a HTML hex string -pub fn color_parse(html_hex: &str) -> anyhow::Result { +pub fn color_parse(html_hex: &str) -> anyhow::Result { if html_hex.len() == 7 { if let (Ok(r), Ok(g), Ok(b)) = ( u8::from_str_radix(&html_hex[1..3], 16), u8::from_str_radix(&html_hex[3..5], 16), u8::from_str_radix(&html_hex[5..7], 16), ) { - return Ok(Vec3::new(r as f32 / 255., g as f32 / 255., b as f32 / 255.)); + return Ok(Vec4::new( + r as f32 / 255., + g as f32 / 255., + b as f32 / 255., + 1., + )); + } + } else if html_hex.len() == 9 { + if let (Ok(r), Ok(g), Ok(b), Ok(a)) = ( + u8::from_str_radix(&html_hex[1..3], 16), + u8::from_str_radix(&html_hex[3..5], 16), + u8::from_str_radix(&html_hex[5..7], 16), + u8::from_str_radix(&html_hex[7..9], 16), + ) { + return Ok(Vec4::new( + r as f32 / 255., + g as f32 / 255., + b as f32 / 255., + a as f32 / 255., + )); } } bail!( @@ -51,8 +72,8 @@ pub fn color_parse(html_hex: &str) -> anyhow::Result { pub struct CanvasBuilder { canvas: Canvas, - pub fg_color: Vec3, - pub bg_color: Vec3, + pub fg_color: GuiColor, + pub bg_color: GuiColor, pub font_size: isize, } @@ -66,8 +87,8 @@ impl CanvasBuilder { ) -> anyhow::Result { Ok(Self { canvas: Canvas::new(width, height, graphics, format, data)?, - bg_color: Vec3::ZERO, - fg_color: Vec3::ONE, + bg_color: Vec4::ZERO, + fg_color: Vec4::ONE, font_size: 16, }) } @@ -522,8 +543,8 @@ impl OverlayBackend for Canvas { pub struct Control { pub state: Option, rect: Rect, - fg_color: Vec3, - bg_color: Vec3, + fg_color: GuiColor, + bg_color: GuiColor, text: Arc, size: isize, dirty: bool, @@ -554,8 +575,8 @@ impl Control { w: 0., h: 0., }, - fg_color: Vec3::ONE, - bg_color: Vec3::ZERO, + fg_color: Vec4::ONE, + bg_color: Vec4::ZERO, text: Arc::from(""), dirty: true, size: 24, @@ -581,7 +602,7 @@ impl Control { } #[inline(always)] - pub fn set_fg_color(&mut self, color: Vec3) { + pub fn set_fg_color(&mut self, color: GuiColor) { if self.fg_color == color { return; } @@ -604,10 +625,9 @@ impl Control { self.rect.w, self.rect.h, )?; - let set0 = canvas.pipeline_bg_color.uniform_buffer( - 0, - vec![self.bg_color.x, self.bg_color.y, self.bg_color.z, 1.], - )?; + let set0 = canvas + .pipeline_bg_color + .uniform_buffer(0, self.bg_color.to_array().to_vec())?; canvas.pipeline_bg_color.create_pass( [canvas.width as _, canvas.height as _], vertex_buffer, @@ -624,7 +644,7 @@ impl Control { canvas: &CanvasData, _: &mut AppState, cmd_buffer: &mut WlxCommandBuffer, - color: Vec4, + color: GuiColor, ) -> anyhow::Result<()> { let vertex_buffer = canvas.graphics.upload_verts( canvas.width as _, @@ -676,10 +696,9 @@ impl Control { ImageView::new_default(tex)?, Filter::Linear, )?; - let set1 = canvas.pipeline_fg_glyph.uniform_buffer( - 1, - vec![self.fg_color.x, self.fg_color.y, self.fg_color.z, 1.], - )?; + let set1 = canvas + .pipeline_fg_glyph + .uniform_buffer(1, self.fg_color.to_array().to_vec())?; let pass = canvas.pipeline_fg_glyph.create_pass( [canvas.width as _, canvas.height as _], vertex_buffer, @@ -725,10 +744,9 @@ impl Control { ImageView::new_default(tex)?, Filter::Linear, )?; - let set1 = canvas.pipeline_fg_glyph.uniform_buffer( - 1, - vec![self.fg_color.x, self.fg_color.y, self.fg_color.z, 1.], - )?; + let set1 = canvas + .pipeline_fg_glyph + .uniform_buffer(1, self.fg_color.to_array().to_vec())?; let pass = canvas.pipeline_fg_glyph.create_pass( [canvas.width as _, canvas.height as _], vertex_buffer, diff --git a/src/gui/modular/label.rs b/src/gui/modular/label.rs index ba7ee80..30e31ce 100644 --- a/src/gui/modular/label.rs +++ b/src/gui/modular/label.rs @@ -1,6 +1,6 @@ use chrono::Local; use chrono_tz::Tz; -use glam::Vec3; +use glam::Vec4; use smallvec::SmallVec; use std::{ io::Read, @@ -13,7 +13,7 @@ use crate::{gui::modular::FALLBACK_COLOR, state::AppState}; use serde::Deserialize; -use super::{color_parse_or_default, ExecArgs, ModularControl, ModularData}; +use super::{color_parse_or_default, ExecArgs, GuiColor, ModularControl, ModularData}; #[derive(Deserialize)] #[serde(tag = "source")] @@ -45,9 +45,9 @@ pub enum LabelData { Battery { device: usize, low_threshold: f32, - normal_color: Vec3, - low_color: Vec3, - charging_color: Vec3, + normal_color: GuiColor, + low_color: GuiColor, + charging_color: GuiColor, }, Clock { format: Arc, @@ -86,7 +86,7 @@ pub fn modular_label_init(label: &mut ModularControl, content: &LabelContent) { let tz: Option = timezone.as_ref().map(|tz| { tz.parse().unwrap_or_else(|_| { log::error!("Failed to parse timezone '{}'", &tz); - label.set_fg_color(FALLBACK_COLOR); + label.set_fg_color(*FALLBACK_COLOR); Tz::UTC }) }); @@ -153,7 +153,7 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A }; (text, color) }) - .unwrap_or_else(|| ("".into(), Vec3::ZERO)); + .unwrap_or_else(|| ("".into(), Vec4::ZERO)); control.set_text(&text); control.set_fg_color(color); diff --git a/src/gui/modular/mod.rs b/src/gui/modular/mod.rs index f2aedd8..29e8dbb 100644 --- a/src/gui/modular/mod.rs +++ b/src/gui/modular/mod.rs @@ -4,7 +4,8 @@ pub mod label; use std::sync::Arc; -use glam::Vec3; +use glam::Vec4; +use once_cell::sync::Lazy; use serde::Deserialize; use crate::{backend::common::OverlaySelector, state::AppState}; @@ -19,11 +20,9 @@ use super::{color_parse, Canvas, CanvasBuilder, Control}; type ModularControl = Control<(), ModularData>; type ExecArgs = Vec>; -const FALLBACK_COLOR: Vec3 = Vec3 { - x: 1., - y: 0., - z: 1., -}; +pub type GuiColor = Vec4; + +static FALLBACK_COLOR: Lazy = Lazy::new(|| Vec4::new(1., 0., 1., 1.)); #[derive(Deserialize)] pub struct ModularUiConfig { @@ -130,7 +129,7 @@ pub fn modular_canvas( rect: [x, y, w, h], bg_color, } => { - canvas.bg_color = color_parse(bg_color).unwrap_or(FALLBACK_COLOR); + canvas.bg_color = color_parse(bg_color).unwrap_or(*FALLBACK_COLOR); canvas.panel(*x, *y, *w, *h); } ModularElement::Label { @@ -140,7 +139,7 @@ pub fn modular_canvas( data, } => { canvas.font_size = *font_size; - canvas.fg_color = color_parse(fg_color).unwrap_or(FALLBACK_COLOR); + canvas.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR); let label = canvas.label(*x, *y, *w, *h, empty_str.clone()); modular_label_init(label, data); } @@ -152,8 +151,8 @@ pub fn modular_canvas( text, data, } => { - canvas.bg_color = color_parse(bg_color).unwrap_or(FALLBACK_COLOR); - canvas.fg_color = color_parse(fg_color).unwrap_or(FALLBACK_COLOR); + canvas.bg_color = color_parse(bg_color).unwrap_or(*FALLBACK_COLOR); + canvas.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR); canvas.font_size = *font_size; let button = canvas.button(*x, *y, *w, *h, text.clone()); modular_button_init(button, data); @@ -177,7 +176,7 @@ pub fn modular_canvas( ListLayout::Vertical => (*w, *h / num_buttons), }; - let fg_color = color_parse(fg_color).unwrap_or(FALLBACK_COLOR); + let fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR); canvas.font_size = *font_size; canvas.fg_color = fg_color; @@ -225,8 +224,8 @@ pub fn modular_canvas( ListLayout::Vertical => (*w, *h / num_buttons), }; - canvas.bg_color = color_parse(bg_color).unwrap_or(FALLBACK_COLOR); - canvas.fg_color = color_parse(fg_color).unwrap_or(FALLBACK_COLOR); + canvas.bg_color = color_parse(bg_color).unwrap_or(*FALLBACK_COLOR); + canvas.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR); canvas.font_size = *font_size; for screen in state.screens.iter() { @@ -326,9 +325,9 @@ pub fn modular_canvas( Ok(canvas.build()) } -pub fn color_parse_or_default(color: &str) -> Vec3 { +pub fn color_parse_or_default(color: &str) -> GuiColor { color_parse(color).unwrap_or_else(|e| { log::error!("Failed to parse color '{}': {}", color, e); - FALLBACK_COLOR + *FALLBACK_COLOR }) }