feat: rounded corners

A proof of concept commit for rounded corners. Currently unoptimized and in need of reorganization too. May also make keyboard keys invisible
This commit is contained in:
Adalyn Black
2024-07-19 08:57:32 -07:00
committed by galister
parent a56ed68b44
commit f27c320231
9 changed files with 276 additions and 112 deletions

View File

@@ -39,22 +39,22 @@ impl<D, S> CanvasBuilder<D, S> {
}
// Creates a panel with bg_color inherited from the canvas
pub fn panel(&mut self, x: f32, y: f32, w: f32, h: f32) -> &mut Control<D, S> {
pub fn panel(&mut self, x: f32, y: f32, w: f32, h: f32, r: f32) -> &mut Control<D, S> {
let idx = self.canvas.controls.len();
self.canvas.controls.push(Control {
rect: Rect { x, y, w, h },
rect: Rect { x, y, w, h, r },
bg_color: self.bg_color,
on_render_bg: Some(Control::render_rect),
on_render_bg: Some(Control::render_rounded_rect),
..Control::new()
});
&mut self.canvas.controls[idx]
}
// Creates a label with fg_color, font_size inherited from the canvas
pub fn label(&mut self, x: f32, y: f32, w: f32, h: f32, text: Arc<str>) -> &mut Control<D, S> {
pub fn label(&mut self, x: f32, y: f32, w: f32, h: f32, r: f32, text: Arc<str>) -> &mut Control<D, S> {
let idx = self.canvas.controls.len();
self.canvas.controls.push(Control {
rect: Rect { x, y, w, h },
rect: Rect { x, y, w, h, r },
text,
fg_color: self.fg_color,
size: self.font_size,
@@ -72,11 +72,12 @@ impl<D, S> CanvasBuilder<D, S> {
y: f32,
w: f32,
h: f32,
r: f32,
text: Arc<str>,
) -> &mut Control<D, S> {
let idx = self.canvas.controls.len();
self.canvas.controls.push(Control {
rect: Rect { x, y, w, h },
rect: Rect { x, y, w, h, r },
text,
fg_color: self.fg_color,
size: self.font_size,
@@ -90,7 +91,7 @@ impl<D, S> CanvasBuilder<D, S> {
pub fn sprite(&mut self, x: f32, y: f32, w: f32, h: f32) -> &mut Control<D, S> {
let idx = self.canvas.controls.len();
self.canvas.controls.push(Control {
rect: Rect { x, y, w, h },
rect: Rect { x, y, w, h, r: 0. },
on_render_bg: Some(Control::render_sprite_bg),
..Control::new()
});
@@ -101,7 +102,7 @@ impl<D, S> CanvasBuilder<D, S> {
pub fn sprite_interactive(&mut self, x: f32, y: f32, w: f32, h: f32) -> &mut Control<D, S> {
let idx = self.canvas.controls.len();
self.canvas.controls.push(Control {
rect: Rect { x, y, w, h },
rect: Rect { x, y, w, h, r: 0. },
on_render_bg: Some(Control::render_sprite_bg),
on_render_hl: Some(Control::render_sprite_hl),
..Control::new()
@@ -110,17 +111,17 @@ impl<D, S> CanvasBuilder<D, S> {
}
// Creates a button with fg_color, bg_color, font_size inherited from the canvas
pub fn button(&mut self, x: f32, y: f32, w: f32, h: f32, text: Arc<str>) -> &mut Control<D, S> {
pub fn button(&mut self, x: f32, y: f32, w: f32, h: f32, r: f32, text: Arc<str>) -> &mut Control<D, S> {
let idx = self.canvas.controls.len();
self.canvas.interactive_set_idx(x, y, w, h, idx);
self.canvas.controls.push(Control {
rect: Rect { x, y, w, h },
rect: Rect { x, y, w, h, r },
text,
fg_color: self.fg_color,
bg_color: self.bg_color,
size: self.font_size,
on_render_bg: Some(Control::render_rect),
on_render_bg: Some(Control::render_rounded_rect),
on_render_fg: Some(Control::render_text_centered),
on_render_hl: Some(Control::render_highlight),
..Control::new()
@@ -135,6 +136,7 @@ impl<D, S> CanvasBuilder<D, S> {
y: f32,
w: f32,
h: f32,
r: f32,
cap_type: KeyCapType,
label: &[String],
) -> &mut Control<D, S> {
@@ -142,9 +144,9 @@ impl<D, S> CanvasBuilder<D, S> {
self.canvas.interactive_set_idx(x, y, w, h, idx);
self.canvas.controls.push(Control {
rect: Rect { x, y, w, h },
rect: Rect { x, y, w, h, r },
bg_color: self.bg_color,
on_render_bg: Some(Control::render_rect),
on_render_bg: Some(Control::render_rounded_rect),
on_render_hl: Some(Control::render_highlight),
..Control::new()
});
@@ -157,6 +159,7 @@ impl<D, S> CanvasBuilder<D, S> {
y,
w,
h: h - self.font_size as f32,
r: 0.,
};
vec![(render, rect, 1f32)]
}
@@ -167,12 +170,14 @@ impl<D, S> CanvasBuilder<D, S> {
y: y + (self.font_size as f32) + 12.,
w,
h,
r: 0.,
};
let rect1 = Rect {
x: x + w * 0.5 + 12.,
y: y + h - (self.font_size as f32) + 8.,
w,
h,
r: 0.,
};
vec![(render, rect0, 1.0), (render, rect1, 0.8)]
}
@@ -183,12 +188,14 @@ impl<D, S> CanvasBuilder<D, S> {
y: y + 2.0,
w,
h: h * 0.5,
r: 0.,
};
let rect1 = Rect {
x,
y: y + h * 0.5 + 2.0,
w,
h: h * 0.5,
r: 0.,
};
vec![(render, rect1, 1.0), (render, rect0, 0.8)]
}
@@ -199,18 +206,21 @@ impl<D, S> CanvasBuilder<D, S> {
y: y + (self.font_size as f32) + 8.,
w,
h,
r: 0.,
};
let rect1 = Rect {
x: x + 12.,
y: y + h - (self.font_size as f32) + 4.,
w,
h,
r: 0.,
};
let rect2 = Rect {
x: x + w * 0.5 + 8.,
y: y + h - (self.font_size as f32) + 4.,
w,
h,
r: 0.,
};
vec![
(render, rect1, 1.0),

View File

@@ -1,9 +1,12 @@
use glam::Vec4;
use std::sync::Arc;
use vulkano::image::view::ImageView;
use std::{sync::Arc, f32::consts::PI};
use vulkano::{
buffer::{Buffer, BufferUsage, BufferCreateInfo},
image::view::ImageView,
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter}};
use crate::{
backend::input::PointerMode, graphics::WlxCommandBuffer, gui::GuiColor, state::AppState,
backend::input::PointerMode, graphics::{WlxCommandBuffer, Vert2Uv}, gui::GuiColor, state::AppState,
};
use super::{CanvasData, Rect};
@@ -49,6 +52,7 @@ impl<D, S> Control<D, S> {
y: 0.,
w: 0.,
h: 0.,
r: 0.,
},
fg_color: Vec4::ONE,
bg_color: Vec4::ZERO,
@@ -102,6 +106,153 @@ impl<D, S> Control<D, S> {
self.dirty = true;
}
pub fn render_rounded_rect(
&self,
canvas: &CanvasData<D>,
_: &mut AppState,
cmd_buffer: &mut WlxCommandBuffer,
) -> anyhow::Result<()> {
let pass = {
let r = self.rect.r.min(self.rect.w / 2.0).min(self.rect.h / 2.0);
let rw = r / canvas.width as f32;
let ruw = r / self.rect.w as f32;
let rh = r / canvas.height as f32;
let ruh = r / self.rect.h as f32;
let x0 = self.rect.x / canvas.width as f32 + rw;
let y0 = self.rect.y / canvas.height as f32 + rh;
let x1 = self.rect.w / canvas.width as f32 + x0 - rw - rw;
let y1 = self.rect.h / canvas.height as f32 + y0 - rh - rh;
let pi6s = (PI/6.).sin();
let pi6c = (PI/6.).cos();
let pi3s = (PI/3.).sin();
let pi3c = (PI/3.).cos();
let vertices = [
// Top Left Corner (0-3)
Vert2Uv {
in_pos: [x0 - rw, y0],
in_uv: [0.0, ruh],
},
Vert2Uv {
in_pos: [x0 - rw * pi6c, y0 - rh * pi6s],
in_uv: [ruw - ruw * pi6c, ruh - ruh * pi6s],
},
Vert2Uv {
in_pos: [x0 - rw * pi3c, y0 - rh * pi3s],
in_uv: [ruw - ruw * pi3c, ruh - ruh * pi3s],
},
Vert2Uv {
in_pos: [x0, y0 - rh],
in_uv: [ruw, 0.0],
},
// Top Right Corner (4-7)
Vert2Uv {
in_pos: [x1, y0 - rh],
in_uv: [1.0 - ruw, 0.0],
},
Vert2Uv {
in_pos: [x1 + rw * pi3c, y0 - rh * pi3s],
in_uv: [1.0 - ruw + ruw * pi3c, ruh - ruh * pi3s],
},
Vert2Uv {
in_pos: [x1 + rw * pi6c, y0 - rh * pi6s],
in_uv: [1.0 - ruw + ruw * pi6c, ruh - ruh * pi6s],
},
Vert2Uv {
in_pos: [x1 + rw, y0],
in_uv: [1.0, ruh],
},
// Bottom Right Corner (8-11)
Vert2Uv {
in_pos: [x1 + rw, y1],
in_uv: [1.0, 1.0 - ruh],
},
Vert2Uv {
in_pos: [x1 + rw * pi6c, y1 + rh * pi6s],
in_uv: [1.0 - ruw + ruw * pi6c, 1.0 - ruh + ruh * pi6s],
},
Vert2Uv {
in_pos: [x1 + rw * pi3c, y1 + rh * pi3s],
in_uv: [1.0 - ruw + ruw * pi3c, 1.0 - ruh + ruh * pi3s],
},
Vert2Uv {
in_pos: [x1, y1 + rh],
in_uv: [1.0 - ruw, 1.0],
},
// Bottom Left Corner (12-15)
Vert2Uv {
in_pos: [x0, y1 + rh],
in_uv: [ruw, 1.0],
},
Vert2Uv {
in_pos: [x0 - rw * pi3c, y1 + rh * pi3s],
in_uv: [ruw - ruw * pi3c, 1.0 - ruh + ruh * pi3s],
},
Vert2Uv {
in_pos: [x0 - rw * pi6c, y1 + rh * pi6s],
in_uv: [ruw - ruw * pi6c, 1.0 - ruh + ruh * pi6s],
},
Vert2Uv {
in_pos: [x0 - rw, y1],
in_uv: [0.0, 1.0 - ruh],
},
];
let mut vertex_string = String::from("[");
for vertex in vertices.iter() {
vertex_string.push('(');
vertex_string.push_str(&vertex.in_uv[0].to_string());
vertex_string.push(',');
vertex_string.push_str(&vertex.in_uv[1].to_string());
vertex_string.push_str("),");
}
vertex_string.push(']');
//log::info!("{}", vertex_string);
let vertex_buffer = canvas.graphics.upload_buffer(BufferUsage::VERTEX_BUFFER, vertices.iter())?;
let set0 = canvas
.pipeline_bg_color
.uniform_buffer(0, self.bg_color.to_array().to_vec())?;
let indices: [u16; 42] =
[0,1,15, 14,15,1
,1,2,14, 13,14,2
,2,3,13, 12,13,3
,3,4,12, 11,12,4
,4,5,11, 10,12,5
,5,6,10, 9,10,6
,6,7,9, 8, 9,7];
canvas.pipeline_bg_color.create_pass(
[canvas.width as _, canvas.height as _],
vertex_buffer,
Buffer::from_iter(
canvas.graphics.memory_allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::INDEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
indices.iter().cloned(),
)?,
vec![set0],
)?
};
cmd_buffer.run_ref(&pass)
}
pub(super) fn render_rect(
&self,
canvas: &CanvasData<D>,

View File

@@ -26,6 +26,7 @@ pub struct Rect {
y: f32,
w: f32,
h: f32,
r: f32,
}
pub struct CanvasData<D> {

View File

@@ -53,18 +53,18 @@ pub struct OverlayListTemplate {
#[serde(tag = "type")]
pub enum ModularElement {
Panel {
rect: [f32; 4],
rect: [f32; 5],
bg_color: Arc<str>,
},
Label {
rect: [f32; 4],
rect: [f32; 5],
font_size: isize,
fg_color: Arc<str>,
#[serde(flatten)]
data: LabelContent,
},
CenteredLabel {
rect: [f32; 4],
rect: [f32; 5],
font_size: isize,
fg_color: Arc<str>,
#[serde(flatten)]
@@ -76,7 +76,7 @@ pub enum ModularElement {
sprite_st: Option<[f32; 4]>,
},
Button {
rect: [f32; 4],
rect: [f32; 5],
font_size: isize,
fg_color: Arc<str>,
bg_color: Arc<str>,
@@ -86,7 +86,7 @@ pub enum ModularElement {
},
/// Convenience type to save you from having to create a bunch of labels
BatteryList {
rect: [f32; 4],
rect: [f32; 5],
font_size: isize,
fg_color: Arc<str>,
fg_color_low: Arc<str>,
@@ -96,7 +96,7 @@ pub enum ModularElement {
layout: ListLayout,
},
OverlayList {
rect: [f32; 4],
rect: [f32; 5],
font_size: isize,
fg_color: Arc<str>,
bg_color: Arc<str>,
@@ -139,32 +139,32 @@ pub fn modular_canvas(
for elem in elements.iter() {
match elem {
ModularElement::Panel {
rect: [x, y, w, h],
rect: [x, y, w, h, r],
bg_color,
} => {
canvas.bg_color = color_parse(bg_color).unwrap_or(*FALLBACK_COLOR);
canvas.panel(*x, *y, *w, *h);
canvas.panel(*x, *y, *w, *h, *r);
}
ModularElement::Label {
rect: [x, y, w, h],
rect: [x, y, w, h, r],
font_size,
fg_color,
data,
} => {
canvas.font_size = *font_size;
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, *r, empty_str.clone());
modular_label_init(label, data);
}
ModularElement::CenteredLabel {
rect: [x, y, w, h],
rect: [x, y, w, h, r],
font_size,
fg_color,
data,
} => {
canvas.font_size = *font_size;
canvas.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR);
let label = canvas.label_centered(*x, *y, *w, *h, empty_str.clone());
let label = canvas.label_centered(*x, *y, *w, *h, *r, empty_str.clone());
modular_label_init(label, data);
}
ModularElement::Sprite {
@@ -187,7 +187,7 @@ pub fn modular_canvas(
}
},
ModularElement::Button {
rect: [x, y, w, h],
rect: [x, y, w, h, r],
font_size,
bg_color,
fg_color,
@@ -197,11 +197,11 @@ pub fn modular_canvas(
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());
let button = canvas.button(*x, *y, *w, *h, *r, text.clone());
modular_button_init(button, data);
}
ModularElement::BatteryList {
rect: [x, y, w, h],
rect: [x, y, w, h, r],
font_size,
fg_color,
fg_color_low,
@@ -229,6 +229,7 @@ pub fn modular_canvas(
button_y + 2.,
button_w - 4.,
button_h - 4.,
*r,
empty_str.clone(),
);
modular_label_init(
@@ -252,7 +253,7 @@ pub fn modular_canvas(
}
}
ModularElement::OverlayList {
rect: [x, y, w, h],
rect: [x, y, w, h, r],
font_size,
fg_color,
bg_color,
@@ -277,6 +278,7 @@ pub fn modular_canvas(
button_y + 2.,
button_w - 4.,
button_h - 4.,
*r,
screen.name.clone(),
);