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"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bitflags = "^1"
|
||||||
glam = "^0.21"
|
glam = "^0.21"
|
||||||
keyframe = "1"
|
keyframe = "1"
|
||||||
wee_alloc = "^0.4"
|
wee_alloc = "^0.4"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = 3
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
|
|
96
src/draw.rs
96
src/draw.rs
|
@ -1,5 +1,6 @@
|
||||||
use crate::abi::UiPanel;
|
use crate::abi::UiPanel;
|
||||||
use crate::{Color, Vec2};
|
use crate::{Color, Vec2};
|
||||||
|
use bitflags::bitflags;
|
||||||
|
|
||||||
pub enum Corner {
|
pub enum Corner {
|
||||||
TopRight,
|
TopRight,
|
||||||
|
@ -8,6 +9,20 @@ pub enum Corner {
|
||||||
TopLeft,
|
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 {
|
pub struct DrawContext {
|
||||||
panel: UiPanel,
|
panel: UiPanel,
|
||||||
offset: Vec2,
|
offset: Vec2,
|
||||||
|
@ -108,30 +123,85 @@ impl DrawContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_rounded_rect(&self, xy: Vec2, size: Vec2, radius: f32, color: Color) {
|
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 xoff = Vec2::new(radius, 0.0);
|
||||||
let yoff = Vec2::new(0.0, radius);
|
let yoff = Vec2::new(0.0, radius);
|
||||||
let sizex = Vec2::new(size.x, 0.0);
|
let sizex = Vec2::new(size.x, 0.0);
|
||||||
let sizey = Vec2::new(0.0, size.y);
|
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 tr = xy + size - xoff - yoff;
|
||||||
let br = xy + sizex - xoff + yoff;
|
let br = xy + sizex - xoff + yoff;
|
||||||
let bl = xy + xoff + yoff;
|
let bl = xy + xoff + yoff;
|
||||||
let tl = xy + sizey + xoff - yoff;
|
let tl = xy + sizey + xoff - yoff;
|
||||||
|
|
||||||
self.draw_quarter_circle(Corner::TopRight, tr, radius, color);
|
if has_bottom {
|
||||||
self.draw_quarter_circle(Corner::BottomRight, br, radius, color);
|
let mut bottom_xy = xy;
|
||||||
self.draw_quarter_circle(Corner::BottomLeft, bl, radius, color);
|
let mut bottom_size = edge_size;
|
||||||
self.draw_quarter_circle(Corner::TopLeft, tl, radius, color);
|
|
||||||
|
|
||||||
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 {
|
pub fn with_offset(&self, offset: Vec2) -> Self {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::anim::Animation;
|
use crate::anim::Animation;
|
||||||
use crate::draw::{Corner, DrawContext};
|
use crate::draw::{Corner, CornerFlags, DrawContext};
|
||||||
use crate::{Color, CursorEventKind, Vec2};
|
use crate::{Color, CursorEventKind, Vec2};
|
||||||
use keyframe::functions::*;
|
use keyframe::functions::*;
|
||||||
|
|
||||||
|
@ -93,6 +93,8 @@ impl Widget for RoundButton {
|
||||||
pub struct RectButton {
|
pub struct RectButton {
|
||||||
pub pos: Vec2,
|
pub pos: Vec2,
|
||||||
pub size: Vec2,
|
pub size: Vec2,
|
||||||
|
pub rounded_corners: CornerFlags,
|
||||||
|
pub radius: f32,
|
||||||
pub was_clicked: bool,
|
pub was_clicked: bool,
|
||||||
pub is_selected: bool,
|
pub is_selected: bool,
|
||||||
pub is_hovering: 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 HOVER_COLOR: Color = Color::new(1., 1., 1., 0.8);
|
||||||
pub const SELECTED_COLOR: Color = Color::new(1., 1., 0., 1.);
|
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 {
|
Self {
|
||||||
pos,
|
pos,
|
||||||
size,
|
size,
|
||||||
|
rounded_corners,
|
||||||
|
radius,
|
||||||
was_clicked: false,
|
was_clicked: false,
|
||||||
is_selected: false,
|
is_selected: false,
|
||||||
is_hovering: false,
|
is_hovering: false,
|
||||||
|
@ -134,7 +138,13 @@ impl Widget for RectButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&mut self, ctx: &DrawContext) {
|
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) {
|
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
|
||||||
|
@ -555,7 +565,15 @@ impl TabMenu {
|
||||||
for i in 0..Self::TAB_NUM {
|
for i in 0..Self::TAB_NUM {
|
||||||
let y = (i + 1) as f32 * Self::TAB_HEIGHT;
|
let y = (i + 1) as f32 * Self::TAB_HEIGHT;
|
||||||
let pos = Vec2::new(0.0, -y);
|
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 }
|
Self { tabs }
|
||||||
|
|
Loading…
Reference in New Issue