Reveal + submenu events

This commit is contained in:
mars 2022-07-10 12:00:46 -06:00
parent 977ce92599
commit 97b993e470
1 changed files with 130 additions and 18 deletions

View File

@ -94,10 +94,18 @@ impl Widget for RoundButton {
pub enum ScrollMenuState {
Opening,
Idle,
Scrolling,
Closing,
Closed,
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum ScrollMenuEvent {
None,
SubmenuOpen(usize),
SubmenuClose(usize),
}
pub struct ScrollMenuButton<T> {
pub widget: T,
pub slide_anim: Animation<EaseOut>,
@ -109,7 +117,9 @@ pub struct ScrollMenu<T> {
pub spacing: f32,
pub scroll_anim: Animation<EaseInOutQuint>,
pub state: ScrollMenuState,
pub selected: usize,
pub was_clicked: Option<usize>,
pub event: ScrollMenuEvent,
}
impl<T> ScrollMenu<T> {
@ -146,22 +156,32 @@ impl<T> ScrollMenu<T> {
Self {
buttons,
spacing,
scroll_anim: Animation::new(EaseInOutQuint, 0.2, 0.0, 0.0),
scroll_anim: Animation::new(EaseInOutQuint, 0.25, 0.0, 0.0),
state: ScrollMenuState::Opening,
selected: 0,
was_clicked: None,
event: ScrollMenuEvent::None,
}
}
pub fn was_clicked(&self) -> Option<usize> {
pub fn get_event(&self) -> ScrollMenuEvent {
self.event
}
pub fn get_was_clicked(&self) -> Option<usize> {
self.was_clicked
}
pub fn scroll_to(&mut self, button_id: usize) {
pub fn select(&mut self, button_id: usize) {
self.scroll_anim.ease_to(button_id as f32);
self.state = ScrollMenuState::Scrolling;
self.event = ScrollMenuEvent::SubmenuClose(self.selected);
self.selected = button_id;
}
pub fn close(&mut self) {
self.state = ScrollMenuState::Closing;
self.event = ScrollMenuEvent::SubmenuClose(self.selected);
for button in self.buttons.iter_mut() {
button.slide_anim.ease_out();
@ -194,19 +214,27 @@ impl<T> ScrollMenu<T> {
impl<T: Widget + Button> Widget for ScrollMenu<T> {
fn update(&mut self, dt: f32) {
self.event = ScrollMenuEvent::None;
self.was_clicked = None;
match self.state {
ScrollMenuState::Idle => {
self.scroll_anim.update(dt);
self.for_buttons(|button, _i, _y| {
button.widget.update(dt);
});
}
ScrollMenuState::Opening => {
if self.animate_buttons(dt) {
self.state = ScrollMenuState::Idle;
self.event = ScrollMenuEvent::SubmenuOpen(self.selected);
}
}
ScrollMenuState::Idle => {}
ScrollMenuState::Scrolling => {
self.for_buttons(|button, _i, _y| {
button.widget.update(dt);
});
self.scroll_anim.update(dt);
if !self.scroll_anim.is_active() {
self.state = ScrollMenuState::Idle;
self.event = ScrollMenuEvent::SubmenuOpen(self.selected);
}
}
ScrollMenuState::Closing => {
@ -214,8 +242,14 @@ impl<T: Widget + Button> Widget for ScrollMenu<T> {
self.state = ScrollMenuState::Closed;
}
}
ScrollMenuState::Closed => {}
ScrollMenuState::Closed => {
return;
}
}
self.for_buttons(|button, _i, _y| {
button.widget.update(dt);
});
}
fn draw(&mut self, ctx: &DrawContext) {
@ -253,13 +287,81 @@ impl<T: Widget + Button> Widget for ScrollMenu<T> {
}
});
self.was_clicked = was_clicked;
if let Some(clicked) = was_clicked {
if clicked != self.selected {
self.was_clicked = Some(clicked);
}
}
}
}
pub struct Reveal<T> {
inner: T,
slide_anim: Animation<EaseIn>,
opacity_anim: Animation<EaseOut>,
state: bool,
}
impl<T: Widget> Reveal<T> {
pub fn new(inner: T, slide: f32, duration: f32) -> Self {
Self {
inner,
slide_anim: Animation::new(EaseIn, duration, slide, 0.0),
opacity_anim: Animation::new(EaseOut, duration, 0.0, 1.0),
state: false,
}
}
pub fn get_offset(&self) -> Vec2 {
Vec2::new(self.slide_anim.get(), 0.0)
}
pub fn show(&mut self) {
self.state = true;
self.slide_anim.ease_in();
self.opacity_anim.ease_in();
}
pub fn hide(&mut self) {
self.state = false;
self.slide_anim.ease_out();
self.opacity_anim.ease_out();
}
}
impl<T: Widget> Widget for Reveal<T> {
fn update(&mut self, dt: f32) {
self.slide_anim.update(dt);
self.opacity_anim.update(dt);
self.inner.update(dt);
}
fn draw(&mut self, ctx: &DrawContext) {
let ctx = ctx.with_offset(Vec2::new(self.slide_anim.get(), 0.0));
let ctx = if self.opacity_anim.is_active() {
ctx.with_opacity(self.opacity_anim.get())
} else if self.state {
ctx
} else {
return;
};
self.inner.draw(&ctx);
}
fn on_cursor_event(&mut self, kind: CursorEventKind, mut at: Vec2) {
if !self.state || self.opacity_anim.is_active() {
return;
}
at -= Vec2::new(self.slide_anim.get(), 0.0);
self.inner.on_cursor_event(kind, at);
}
}
pub struct MainMenu {
pub menu: ScrollMenu<RoundButton>,
pub inventory: Inventory,
pub inventory: Reveal<Inventory>,
}
impl Default for MainMenu {
@ -270,28 +372,38 @@ impl Default for MainMenu {
buttons.push(button);
}
let inventory = Inventory::new();
let inventory = Reveal::new(inventory, -0.02, 0.1);
Self {
menu: ScrollMenu::new(buttons, 0.1),
inventory: Inventory::new(),
inventory,
}
}
}
impl Widget for MainMenu {
fn update(&mut self, dt: f32) {
match self.menu.was_clicked() {
match self.menu.get_was_clicked() {
None => {}
Some(4) => self.menu.close(),
Some(button) => self.menu.scroll_to(button),
Some(button) => self.menu.select(button),
};
match self.menu.get_event() {
ScrollMenuEvent::SubmenuOpen(0) => self.inventory.show(),
ScrollMenuEvent::SubmenuClose(0) => self.inventory.hide(),
_ => {}
};
self.menu.update(dt);
self.inventory.update(dt);
}
fn draw(&mut self, ctx: &DrawContext) {
self.menu.draw(&ctx);
let inventory_ctx = ctx.with_offset(Vec2::new(0.1, 0.0));
let inventory_ctx = ctx.with_offset(Vec2::new(0.05, 0.0));
self.inventory.draw(&inventory_ctx);
}
@ -335,7 +447,7 @@ impl Widget for Inventory {
let tab_list_height = tab_num as f32 * tab_height;
let separator_xy = Vec2::new(tab_width, separator_width - tab_list_height);
let separator_size = Vec2::new(separator_width, tab_list_height - separator_width);
let body_width = box_grid_width as f32 * (box_size + box_padding) + box_margin;
let body_width = box_grid_width as f32 * (box_size + box_padding) + box_margin * 2.0;
let body_height = tab_list_height - box_margin * 2.0;
let head_width = tab_width + separator_width + body_width;
let head_inner_xy = Vec2::ZERO;