RectButton icons
This commit is contained in:
parent
e070a54bb6
commit
a6492622b6
|
@ -1,5 +1,7 @@
|
|||
use super::*;
|
||||
|
||||
use text::Icon;
|
||||
|
||||
pub trait Button {
|
||||
fn was_clicked(&self) -> bool;
|
||||
}
|
||||
|
@ -20,36 +22,31 @@ pub struct RoundButton {
|
|||
shrink_anim: Animation<EaseOutQuint>,
|
||||
was_clicked: bool,
|
||||
state: ButtonState,
|
||||
label: Option<Label>,
|
||||
icon: Option<Icon>,
|
||||
}
|
||||
|
||||
impl RoundButton {
|
||||
pub fn new(label: Option<LabelText>) -> Self {
|
||||
pub fn new(icon: Option<LabelText>) -> Self {
|
||||
let pos = Vec2::ZERO;
|
||||
let radius = 0.05;
|
||||
|
||||
let label = label.map(|text| {
|
||||
let icon = icon.map(|text| {
|
||||
let scale = radius * 1.5;
|
||||
let alignment = HorizontalAlignment::Center;
|
||||
let left = -radius;
|
||||
let right = radius;
|
||||
let baseline = 0.0;
|
||||
let center = pos;
|
||||
let color = Color::BLACK;
|
||||
let center_y = true;
|
||||
|
||||
Label::new(
|
||||
text, alignment, scale, color, left, right, baseline, center_y,
|
||||
)
|
||||
Icon::new(text, scale, color, center)
|
||||
});
|
||||
|
||||
Self {
|
||||
pos: Default::default(),
|
||||
pos,
|
||||
radius,
|
||||
spacing: 0.01,
|
||||
thickness: 0.002,
|
||||
shrink_anim: Animation::new(EaseOutQuint, 0.1, 1.0, 0.0),
|
||||
was_clicked: false,
|
||||
state: ButtonState::Idle,
|
||||
label,
|
||||
icon,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +75,7 @@ impl Widget for RoundButton {
|
|||
ctx.draw_circle(self.pos, self.radius, color);
|
||||
ctx.draw_ring(self.pos, self.radius + spacing, self.thickness, color);
|
||||
|
||||
self.label.draw(ctx);
|
||||
self.icon.draw(ctx);
|
||||
}
|
||||
|
||||
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
|
||||
|
@ -105,6 +102,10 @@ impl Widget for RoundButton {
|
|||
pub struct RectButtonStyle {
|
||||
pub rounded_corners: CornerFlags,
|
||||
pub radius: f32,
|
||||
pub label_scale_factor: f32,
|
||||
pub label_baseline: f32,
|
||||
pub icon_scale_factor: f32,
|
||||
pub icon_margin_factor: f32,
|
||||
pub inactive_color: Color,
|
||||
pub hover_color: Color,
|
||||
pub selected_color: Color,
|
||||
|
@ -115,6 +116,10 @@ impl Default for RectButtonStyle {
|
|||
Self {
|
||||
rounded_corners: CornerFlags::empty(),
|
||||
radius: 0.0,
|
||||
label_scale_factor: 0.65,
|
||||
label_baseline: 0.25,
|
||||
icon_scale_factor: 0.8,
|
||||
icon_margin_factor: 1.1,
|
||||
inactive_color: Color::new(1., 1., 1., 0.2),
|
||||
hover_color: Color::new(1., 1., 1., 0.8),
|
||||
selected_color: Color::new(1., 1., 0., 1.),
|
||||
|
@ -130,6 +135,7 @@ pub struct RectButton {
|
|||
pub is_hovering: bool,
|
||||
pub color_anim: Animation<EaseInQuad, Color>,
|
||||
pub label: Option<Label>,
|
||||
pub icon: Option<Icon>,
|
||||
}
|
||||
|
||||
impl Button for RectButton {
|
||||
|
@ -139,23 +145,32 @@ impl Button for RectButton {
|
|||
}
|
||||
|
||||
impl RectButton {
|
||||
pub fn new(style: RectButtonStyle, label: Option<LabelText>, rect: Rect) -> Self {
|
||||
let label_height_scale = 0.7;
|
||||
let label_baseline_scale = 0.25;
|
||||
pub fn new(style: RectButtonStyle, rect: Rect, label: Option<LabelText>, icon: Option<LabelText>) -> Self {
|
||||
let mut label_left = rect.bl.x;
|
||||
let mut alignment = HorizontalAlignment::Center;
|
||||
|
||||
let icon = icon.map(|text| {
|
||||
let margin = rect.height() * style.icon_margin_factor;
|
||||
label_left += margin;
|
||||
alignment = HorizontalAlignment::Left;
|
||||
let scale = rect.height() * style.icon_scale_factor;
|
||||
let color = Color::BLACK;
|
||||
let cx = rect.bl.x + margin / 2.0;
|
||||
let cy = rect.bl.y + rect.height() / 2.0;
|
||||
let center = Vec2::new(cx, cy);
|
||||
|
||||
Icon::new(text, scale, color, center)
|
||||
});
|
||||
|
||||
let label = label.map(|text| {
|
||||
let scale = rect.height() * label_height_scale;
|
||||
let alignment = HorizontalAlignment::Center;
|
||||
let left = rect.bl.x;
|
||||
let scale = rect.height() * style.label_scale_factor;
|
||||
let left = label_left;
|
||||
let right = rect.tr.x;
|
||||
let baseline = rect.bl.y;
|
||||
let baseline = (rect.height() * label_baseline_scale) + baseline;
|
||||
let baseline = (rect.height() * style.label_baseline) + baseline;
|
||||
let color = Color::BLACK;
|
||||
let center_y = false;
|
||||
|
||||
Label::new(
|
||||
text, alignment, scale, color, left, right, baseline, center_y,
|
||||
)
|
||||
Label::new(text, alignment, scale, color, left, right, baseline)
|
||||
});
|
||||
|
||||
let color_anim =
|
||||
|
@ -169,6 +184,7 @@ impl RectButton {
|
|||
is_hovering: false,
|
||||
color_anim,
|
||||
label,
|
||||
icon,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +204,7 @@ impl Widget for RectButton {
|
|||
);
|
||||
|
||||
self.label.draw(ctx);
|
||||
self.icon.draw(ctx);
|
||||
}
|
||||
|
||||
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
|
||||
|
|
|
@ -238,7 +238,7 @@ impl TabMenu {
|
|||
}
|
||||
|
||||
let rect = Rect::from_xy_size(pos, tab_size);
|
||||
tabs.push(RectButton::new(style, None, rect));
|
||||
tabs.push(RectButton::new(style, rect, None, None));
|
||||
}
|
||||
|
||||
let tab_list_height = Self::TAB_NUM as f32 * Self::TAB_HEIGHT;
|
||||
|
|
|
@ -173,21 +173,35 @@ pub struct SettingsMenu {
|
|||
|
||||
impl SettingsMenu {
|
||||
pub fn new() -> Self {
|
||||
let font = Font::new("Leon Sans");
|
||||
let button_texts = ["Graphics", "Sound", "Interface", "Network", "Account"];
|
||||
let icon_font = Font::new("Iosevka Nerd Font");
|
||||
let label_font = Font::new("Leon Sans");
|
||||
|
||||
let button_texts = [
|
||||
("Graphics", ""),
|
||||
("Sound", "墳"),
|
||||
("Interface", ""),
|
||||
("Network", "ﴽ"),
|
||||
("Account", "𣏕"),
|
||||
];
|
||||
|
||||
let button_size = Vec2::new(0.4, 0.1);
|
||||
let button_rect = Rect::from_xy_size(Vec2::new(0.0, -button_size.y / 2.0), button_size);
|
||||
|
||||
let mut buttons = Vec::new();
|
||||
for text in button_texts.iter() {
|
||||
let text = LabelText {
|
||||
font,
|
||||
text: text.to_string(),
|
||||
for (label, icon) in button_texts.iter() {
|
||||
let label = LabelText {
|
||||
font: label_font,
|
||||
text: label.to_string(),
|
||||
};
|
||||
|
||||
let icon = LabelText {
|
||||
font: icon_font,
|
||||
text: icon.to_string(),
|
||||
};
|
||||
|
||||
let style = Default::default();
|
||||
|
||||
let button = RectButton::new(style, Some(text), button_rect);
|
||||
let button = RectButton::new(style, button_rect, Some(label), Some(icon));
|
||||
buttons.push(button);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ pub struct Label {
|
|||
left: f32,
|
||||
right: f32,
|
||||
baseline: f32,
|
||||
center_y: bool,
|
||||
dirty: bool,
|
||||
layout: Option<TextLayout>,
|
||||
bounds: Rect,
|
||||
|
@ -36,7 +35,6 @@ impl Label {
|
|||
left: f32,
|
||||
right: f32,
|
||||
baseline: f32,
|
||||
center_y: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
text,
|
||||
|
@ -46,7 +44,6 @@ impl Label {
|
|||
left,
|
||||
right,
|
||||
baseline,
|
||||
center_y,
|
||||
dirty: true,
|
||||
layout: None,
|
||||
bounds: Rect::from_xy_size(Vec2::ZERO, Vec2::ZERO),
|
||||
|
@ -73,13 +70,51 @@ impl Widget for Label {
|
|||
}
|
||||
};
|
||||
|
||||
let yoff = if self.center_y {
|
||||
(bounds.bl.y - bounds.tr.y) / 2.0 - bounds.bl.y
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
self.offset = Vec2::new(xoff, yoff + self.baseline);
|
||||
self.offset = Vec2::new(xoff, self.baseline);
|
||||
self.dirty = false;
|
||||
self.layout = Some(layout);
|
||||
}
|
||||
|
||||
if let Some(layout) = self.layout.as_ref() {
|
||||
ctx.draw_text_layout(layout, self.offset, self.scale, self.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Icon {
|
||||
text: LabelText,
|
||||
scale: f32,
|
||||
color: Color,
|
||||
center: Vec2,
|
||||
dirty: bool,
|
||||
layout: Option<TextLayout>,
|
||||
bounds: Rect,
|
||||
offset: Vec2,
|
||||
}
|
||||
|
||||
impl Icon {
|
||||
pub fn new(text: LabelText, scale: f32, color: Color, center: Vec2) -> Self {
|
||||
Self {
|
||||
text,
|
||||
scale,
|
||||
color,
|
||||
center,
|
||||
dirty: true,
|
||||
layout: None,
|
||||
bounds: Rect::from_xy_size(Vec2::ZERO, Vec2::ZERO),
|
||||
offset: Vec2::ZERO,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Icon {
|
||||
fn draw(&mut self, ctx: &DrawContext) {
|
||||
if self.dirty {
|
||||
let layout = TextLayout::new(&self.text.font, &self.text.text);
|
||||
let bounds = Rect::from(layout.get_bounds()).scale(self.scale);
|
||||
self.bounds = bounds;
|
||||
self.offset = self.center - bounds.size() / 2.0;
|
||||
self.offset.y -= bounds.bl.y;
|
||||
self.dirty = false;
|
||||
self.layout = Some(layout);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,10 @@ impl Rect {
|
|||
self.bl.x < xy.x && self.bl.y < xy.y && self.tr.x > xy.x && self.tr.y > xy.y
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Vec2 {
|
||||
self.tr - self.bl
|
||||
}
|
||||
|
||||
pub fn width(&self) -> f32 {
|
||||
self.tr.x - self.bl.x
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue