Add CornerFlags and draw_partially_rounded_rect()
This commit is contained in:
parent
bfe8ca07a0
commit
f7c2a24572
|
@ -7,10 +7,11 @@ edition = "2021"
|
|||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "^1"
|
||||
glam = "^0.21"
|
||||
keyframe = "1"
|
||||
wee_alloc = "^0.4"
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
opt-level = 3
|
||||
lto = "fat"
|
||||
|
|
96
src/draw.rs
96
src/draw.rs
|
@ -1,5 +1,6 @@
|
|||
use crate::abi::UiPanel;
|
||||
use crate::{Color, Vec2};
|
||||
use bitflags::bitflags;
|
||||
|
||||
pub enum Corner {
|
||||
TopRight,
|
||||
|
@ -8,6 +9,20 @@ pub enum Corner {
|
|||
TopLeft,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct CornerFlags: u8 {
|
||||
const TOP_RIGHT = 0x01;
|
||||
const BOTTOM_RIGHT = 0x02;
|
||||
const BOTTOM_LEFT = 0x04;
|
||||
const TOP_LEFT = 0x08;
|
||||
const TOP = 0x09;
|
||||
const RIGHT = 0x03;
|
||||
const BOTTOM = 0x06;
|
||||
const LEFT = 0x0C;
|
||||
const ALL = 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DrawContext {
|
||||
panel: UiPanel,
|
||||
offset: Vec2,
|
||||
|
@ -108,30 +123,85 @@ impl DrawContext {
|
|||
}
|
||||
|
||||
pub fn draw_rounded_rect(&self, xy: Vec2, size: Vec2, radius: f32, color: Color) {
|
||||
self.draw_partially_rounded_rect(CornerFlags::ALL, xy, size, radius, color);
|
||||
}
|
||||
|
||||
pub fn draw_partially_rounded_rect(
|
||||
&self,
|
||||
corners: CornerFlags,
|
||||
xy: Vec2,
|
||||
size: Vec2,
|
||||
radius: f32,
|
||||
color: Color,
|
||||
) {
|
||||
if corners.is_empty() {
|
||||
self.draw_rect(xy, size, color);
|
||||
return;
|
||||
}
|
||||
|
||||
let has_top = corners.intersects(CornerFlags::TOP);
|
||||
let has_bottom = corners.intersects(CornerFlags::BOTTOM);
|
||||
let edge_size = Vec2::new(size.x, radius);
|
||||
|
||||
let xoff = Vec2::new(radius, 0.0);
|
||||
let yoff = Vec2::new(0.0, radius);
|
||||
let sizex = Vec2::new(size.x, 0.0);
|
||||
let sizey = Vec2::new(0.0, size.y);
|
||||
let inner_size = size - Vec2::new(radius, radius) * 2.0;
|
||||
let lr_edge_size = Vec2::new(radius, inner_size.y);
|
||||
let tb_edge_size = Vec2::new(inner_size.x, radius);
|
||||
|
||||
self.draw_rect(xy + yoff, lr_edge_size, color); // left edge
|
||||
self.draw_rect(xy + yoff + sizex - xoff, lr_edge_size, color); // right edge
|
||||
self.draw_rect(xy + xoff, tb_edge_size, color); // bottom edge
|
||||
self.draw_rect(xy + xoff + sizey - yoff, tb_edge_size, color); // top edge
|
||||
|
||||
let tr = xy + size - xoff - yoff;
|
||||
let br = xy + sizex - xoff + yoff;
|
||||
let bl = xy + xoff + yoff;
|
||||
let tl = xy + sizey + xoff - yoff;
|
||||
|
||||
self.draw_quarter_circle(Corner::TopRight, tr, radius, color);
|
||||
self.draw_quarter_circle(Corner::BottomRight, br, radius, color);
|
||||
self.draw_quarter_circle(Corner::BottomLeft, bl, radius, color);
|
||||
self.draw_quarter_circle(Corner::TopLeft, tl, radius, color);
|
||||
if has_bottom {
|
||||
let mut bottom_xy = xy;
|
||||
let mut bottom_size = edge_size;
|
||||
|
||||
self.draw_rect(bl, inner_size, color);
|
||||
if corners.contains(CornerFlags::BOTTOM_LEFT) {
|
||||
bottom_xy.x += radius;
|
||||
bottom_size.x -= radius;
|
||||
self.draw_quarter_circle(Corner::BottomLeft, bl, radius, color);
|
||||
}
|
||||
|
||||
if corners.contains(CornerFlags::BOTTOM_RIGHT) {
|
||||
bottom_size.x -= radius;
|
||||
self.draw_quarter_circle(Corner::BottomRight, br, radius, color);
|
||||
}
|
||||
|
||||
self.draw_rect(bottom_xy, bottom_size, color);
|
||||
}
|
||||
|
||||
if has_top {
|
||||
let mut top_xy = Vec2::new(xy.x, xy.y + size.y - radius);
|
||||
let mut top_size = edge_size;
|
||||
|
||||
if corners.contains(CornerFlags::TOP_LEFT) {
|
||||
top_xy.x += radius;
|
||||
top_size.x -= radius;
|
||||
self.draw_quarter_circle(Corner::TopLeft, tl, radius, color);
|
||||
}
|
||||
|
||||
if corners.contains(CornerFlags::TOP_RIGHT) {
|
||||
top_size.x -= radius;
|
||||
self.draw_quarter_circle(Corner::TopRight, tr, radius, color);
|
||||
}
|
||||
|
||||
self.draw_rect(top_xy, top_size, color);
|
||||
}
|
||||
|
||||
let mut inner_xy = xy;
|
||||
let mut inner_size = size;
|
||||
|
||||
if has_bottom {
|
||||
inner_xy.y += radius;
|
||||
inner_size.y -= radius;
|
||||
}
|
||||
|
||||
if has_top {
|
||||
inner_size.y -= radius;
|
||||
}
|
||||
|
||||
self.draw_rect(inner_xy, inner_size, color);
|
||||
}
|
||||
|
||||
pub fn with_offset(&self, offset: Vec2) -> Self {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::anim::Animation;
|
||||
use crate::draw::{Corner, DrawContext};
|
||||
use crate::draw::{Corner, CornerFlags, DrawContext};
|
||||
use crate::{Color, CursorEventKind, Vec2};
|
||||
use keyframe::functions::*;
|
||||
|
||||
|
@ -93,6 +93,8 @@ impl Widget for RoundButton {
|
|||
pub struct RectButton {
|
||||
pub pos: Vec2,
|
||||
pub size: Vec2,
|
||||
pub rounded_corners: CornerFlags,
|
||||
pub radius: f32,
|
||||
pub was_clicked: bool,
|
||||
pub is_selected: bool,
|
||||
pub is_hovering: bool,
|
||||
|
@ -110,10 +112,12 @@ impl RectButton {
|
|||
pub const HOVER_COLOR: Color = Color::new(1., 1., 1., 0.8);
|
||||
pub const SELECTED_COLOR: Color = Color::new(1., 1., 0., 1.);
|
||||
|
||||
pub fn new(pos: Vec2, size: Vec2) -> Self {
|
||||
pub fn new(pos: Vec2, size: Vec2, rounded_corners: CornerFlags, radius: f32) -> Self {
|
||||
Self {
|
||||
pos,
|
||||
size,
|
||||
rounded_corners,
|
||||
radius,
|
||||
was_clicked: false,
|
||||
is_selected: false,
|
||||
is_hovering: false,
|
||||
|
@ -134,7 +138,13 @@ impl Widget for RectButton {
|
|||
}
|
||||
|
||||
fn draw(&mut self, ctx: &DrawContext) {
|
||||
ctx.draw_rect(self.pos, self.size, self.color_anim.get());
|
||||
ctx.draw_partially_rounded_rect(
|
||||
self.rounded_corners,
|
||||
self.pos,
|
||||
self.size,
|
||||
self.radius,
|
||||
self.color_anim.get(),
|
||||
);
|
||||
}
|
||||
|
||||
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
|
||||
|
@ -555,7 +565,15 @@ impl TabMenu {
|
|||
for i in 0..Self::TAB_NUM {
|
||||
let y = (i + 1) as f32 * Self::TAB_HEIGHT;
|
||||
let pos = Vec2::new(0.0, -y);
|
||||
tabs.push(RectButton::new(pos, tab_size));
|
||||
let radius = Self::HEAD_RADIUS;
|
||||
|
||||
let corners = if i == Self::TAB_NUM - 1 {
|
||||
CornerFlags::BOTTOM_LEFT
|
||||
} else {
|
||||
CornerFlags::empty()
|
||||
};
|
||||
|
||||
tabs.push(RectButton::new(pos, tab_size, corners, radius));
|
||||
}
|
||||
|
||||
Self { tabs }
|
||||
|
|
Loading…
Reference in New Issue