feat: canvas alpha

This commit is contained in:
galister
2024-04-14 17:48:44 +09:00
parent d99a58da9e
commit 7184a9f21f
3 changed files with 64 additions and 47 deletions

View File

@@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use anyhow::bail; use anyhow::bail;
use glam::{Vec2, Vec3, Vec4}; use glam::{Vec2, Vec4};
use vulkano::{ use vulkano::{
command_buffer::CommandBufferUsage, command_buffer::CommandBufferUsage,
format::Format, format::Format,
@@ -19,6 +19,8 @@ use crate::{
state::AppState, state::AppState,
}; };
use self::modular::GuiColor;
pub mod font; pub mod font;
pub mod modular; pub mod modular;
@@ -32,14 +34,33 @@ struct Rect {
} }
// Parses a color from a HTML hex string // Parses a color from a HTML hex string
pub fn color_parse(html_hex: &str) -> anyhow::Result<Vec3> { pub fn color_parse(html_hex: &str) -> anyhow::Result<GuiColor> {
if html_hex.len() == 7 { if html_hex.len() == 7 {
if let (Ok(r), Ok(g), Ok(b)) = ( if let (Ok(r), Ok(g), Ok(b)) = (
u8::from_str_radix(&html_hex[1..3], 16), u8::from_str_radix(&html_hex[1..3], 16),
u8::from_str_radix(&html_hex[3..5], 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[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!( bail!(
@@ -51,8 +72,8 @@ pub fn color_parse(html_hex: &str) -> anyhow::Result<Vec3> {
pub struct CanvasBuilder<D, S> { pub struct CanvasBuilder<D, S> {
canvas: Canvas<D, S>, canvas: Canvas<D, S>,
pub fg_color: Vec3, pub fg_color: GuiColor,
pub bg_color: Vec3, pub bg_color: GuiColor,
pub font_size: isize, pub font_size: isize,
} }
@@ -66,8 +87,8 @@ impl<D, S> CanvasBuilder<D, S> {
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
Ok(Self { Ok(Self {
canvas: Canvas::new(width, height, graphics, format, data)?, canvas: Canvas::new(width, height, graphics, format, data)?,
bg_color: Vec3::ZERO, bg_color: Vec4::ZERO,
fg_color: Vec3::ONE, fg_color: Vec4::ONE,
font_size: 16, font_size: 16,
}) })
} }
@@ -522,8 +543,8 @@ impl<D, S> OverlayBackend for Canvas<D, S> {
pub struct Control<D, S> { pub struct Control<D, S> {
pub state: Option<S>, pub state: Option<S>,
rect: Rect, rect: Rect,
fg_color: Vec3, fg_color: GuiColor,
bg_color: Vec3, bg_color: GuiColor,
text: Arc<str>, text: Arc<str>,
size: isize, size: isize,
dirty: bool, dirty: bool,
@@ -554,8 +575,8 @@ impl<D, S> Control<D, S> {
w: 0., w: 0.,
h: 0., h: 0.,
}, },
fg_color: Vec3::ONE, fg_color: Vec4::ONE,
bg_color: Vec3::ZERO, bg_color: Vec4::ZERO,
text: Arc::from(""), text: Arc::from(""),
dirty: true, dirty: true,
size: 24, size: 24,
@@ -581,7 +602,7 @@ impl<D, S> Control<D, S> {
} }
#[inline(always)] #[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 { if self.fg_color == color {
return; return;
} }
@@ -604,10 +625,9 @@ impl<D, S> Control<D, S> {
self.rect.w, self.rect.w,
self.rect.h, self.rect.h,
)?; )?;
let set0 = canvas.pipeline_bg_color.uniform_buffer( let set0 = canvas
0, .pipeline_bg_color
vec![self.bg_color.x, self.bg_color.y, self.bg_color.z, 1.], .uniform_buffer(0, self.bg_color.to_array().to_vec())?;
)?;
canvas.pipeline_bg_color.create_pass( canvas.pipeline_bg_color.create_pass(
[canvas.width as _, canvas.height as _], [canvas.width as _, canvas.height as _],
vertex_buffer, vertex_buffer,
@@ -624,7 +644,7 @@ impl<D, S> Control<D, S> {
canvas: &CanvasData<D>, canvas: &CanvasData<D>,
_: &mut AppState, _: &mut AppState,
cmd_buffer: &mut WlxCommandBuffer, cmd_buffer: &mut WlxCommandBuffer,
color: Vec4, color: GuiColor,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let vertex_buffer = canvas.graphics.upload_verts( let vertex_buffer = canvas.graphics.upload_verts(
canvas.width as _, canvas.width as _,
@@ -676,10 +696,9 @@ impl<D, S> Control<D, S> {
ImageView::new_default(tex)?, ImageView::new_default(tex)?,
Filter::Linear, Filter::Linear,
)?; )?;
let set1 = canvas.pipeline_fg_glyph.uniform_buffer( let set1 = canvas
1, .pipeline_fg_glyph
vec![self.fg_color.x, self.fg_color.y, self.fg_color.z, 1.], .uniform_buffer(1, self.fg_color.to_array().to_vec())?;
)?;
let pass = canvas.pipeline_fg_glyph.create_pass( let pass = canvas.pipeline_fg_glyph.create_pass(
[canvas.width as _, canvas.height as _], [canvas.width as _, canvas.height as _],
vertex_buffer, vertex_buffer,
@@ -725,10 +744,9 @@ impl<D, S> Control<D, S> {
ImageView::new_default(tex)?, ImageView::new_default(tex)?,
Filter::Linear, Filter::Linear,
)?; )?;
let set1 = canvas.pipeline_fg_glyph.uniform_buffer( let set1 = canvas
1, .pipeline_fg_glyph
vec![self.fg_color.x, self.fg_color.y, self.fg_color.z, 1.], .uniform_buffer(1, self.fg_color.to_array().to_vec())?;
)?;
let pass = canvas.pipeline_fg_glyph.create_pass( let pass = canvas.pipeline_fg_glyph.create_pass(
[canvas.width as _, canvas.height as _], [canvas.width as _, canvas.height as _],
vertex_buffer, vertex_buffer,

View File

@@ -1,6 +1,6 @@
use chrono::Local; use chrono::Local;
use chrono_tz::Tz; use chrono_tz::Tz;
use glam::Vec3; use glam::Vec4;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{ use std::{
io::Read, io::Read,
@@ -13,7 +13,7 @@ use crate::{gui::modular::FALLBACK_COLOR, state::AppState};
use serde::Deserialize; use serde::Deserialize;
use super::{color_parse_or_default, ExecArgs, ModularControl, ModularData}; use super::{color_parse_or_default, ExecArgs, GuiColor, ModularControl, ModularData};
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(tag = "source")] #[serde(tag = "source")]
@@ -45,9 +45,9 @@ pub enum LabelData {
Battery { Battery {
device: usize, device: usize,
low_threshold: f32, low_threshold: f32,
normal_color: Vec3, normal_color: GuiColor,
low_color: Vec3, low_color: GuiColor,
charging_color: Vec3, charging_color: GuiColor,
}, },
Clock { Clock {
format: Arc<str>, format: Arc<str>,
@@ -86,7 +86,7 @@ pub fn modular_label_init(label: &mut ModularControl, content: &LabelContent) {
let tz: Option<Tz> = timezone.as_ref().map(|tz| { let tz: Option<Tz> = timezone.as_ref().map(|tz| {
tz.parse().unwrap_or_else(|_| { tz.parse().unwrap_or_else(|_| {
log::error!("Failed to parse timezone '{}'", &tz); log::error!("Failed to parse timezone '{}'", &tz);
label.set_fg_color(FALLBACK_COLOR); label.set_fg_color(*FALLBACK_COLOR);
Tz::UTC Tz::UTC
}) })
}); });
@@ -153,7 +153,7 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
}; };
(text, color) (text, color)
}) })
.unwrap_or_else(|| ("".into(), Vec3::ZERO)); .unwrap_or_else(|| ("".into(), Vec4::ZERO));
control.set_text(&text); control.set_text(&text);
control.set_fg_color(color); control.set_fg_color(color);

View File

@@ -4,7 +4,8 @@ pub mod label;
use std::sync::Arc; use std::sync::Arc;
use glam::Vec3; use glam::Vec4;
use once_cell::sync::Lazy;
use serde::Deserialize; use serde::Deserialize;
use crate::{backend::common::OverlaySelector, state::AppState}; use crate::{backend::common::OverlaySelector, state::AppState};
@@ -19,11 +20,9 @@ use super::{color_parse, Canvas, CanvasBuilder, Control};
type ModularControl = Control<(), ModularData>; type ModularControl = Control<(), ModularData>;
type ExecArgs = Vec<Arc<str>>; type ExecArgs = Vec<Arc<str>>;
const FALLBACK_COLOR: Vec3 = Vec3 { pub type GuiColor = Vec4;
x: 1.,
y: 0., static FALLBACK_COLOR: Lazy<GuiColor> = Lazy::new(|| Vec4::new(1., 0., 1., 1.));
z: 1.,
};
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct ModularUiConfig { pub struct ModularUiConfig {
@@ -130,7 +129,7 @@ pub fn modular_canvas(
rect: [x, y, w, h], rect: [x, y, w, h],
bg_color, 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); canvas.panel(*x, *y, *w, *h);
} }
ModularElement::Label { ModularElement::Label {
@@ -140,7 +139,7 @@ pub fn modular_canvas(
data, data,
} => { } => {
canvas.font_size = *font_size; 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()); let label = canvas.label(*x, *y, *w, *h, empty_str.clone());
modular_label_init(label, data); modular_label_init(label, data);
} }
@@ -152,8 +151,8 @@ pub fn modular_canvas(
text, text,
data, data,
} => { } => {
canvas.bg_color = color_parse(bg_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.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR);
canvas.font_size = *font_size; canvas.font_size = *font_size;
let button = canvas.button(*x, *y, *w, *h, text.clone()); let button = canvas.button(*x, *y, *w, *h, text.clone());
modular_button_init(button, data); modular_button_init(button, data);
@@ -177,7 +176,7 @@ pub fn modular_canvas(
ListLayout::Vertical => (*w, *h / num_buttons), 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.font_size = *font_size;
canvas.fg_color = fg_color; canvas.fg_color = fg_color;
@@ -225,8 +224,8 @@ pub fn modular_canvas(
ListLayout::Vertical => (*w, *h / num_buttons), ListLayout::Vertical => (*w, *h / num_buttons),
}; };
canvas.bg_color = color_parse(bg_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.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR);
canvas.font_size = *font_size; canvas.font_size = *font_size;
for screen in state.screens.iter() { for screen in state.screens.iter() {
@@ -326,9 +325,9 @@ pub fn modular_canvas(
Ok(canvas.build()) 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| { color_parse(color).unwrap_or_else(|e| {
log::error!("Failed to parse color '{}': {}", color, e); log::error!("Failed to parse color '{}': {}", color, e);
FALLBACK_COLOR *FALLBACK_COLOR
}) })
} }