Implement tab change via button
This commit is contained in:
parent
cdd0959c4c
commit
a629bc666b
6 changed files with 60 additions and 38 deletions
|
@ -54,6 +54,7 @@ sdl2 = { version = "0.37.0" }
|
|||
syn = { version = "2.0.67", features = ["extra-traits", "full"] }
|
||||
quote = "1.0.35"
|
||||
proc-macro2 = "1.0.86"
|
||||
downcast-rs = "1.2.1"
|
||||
|
||||
utilities = { git = "https://gavania.de/hodasemi/utilities.git" }
|
||||
vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
anyhow = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
destructure_traitobject = { workspace = true }
|
||||
downcast-rs = { workspace = true }
|
||||
|
||||
engine = { path = "../engine" }
|
||||
rpg_components = { path = "../rpg_components" }
|
|
@ -56,7 +56,7 @@ impl<A: Ability + 'static> AbilityPage<A> {
|
|||
|
||||
// abilities
|
||||
let ability_mode = PageContent::new(
|
||||
Content::new(&engine, reference.clone(), {
|
||||
Content::new::<_, Self>(&engine, reference.clone(), {
|
||||
let engine = engine.clone();
|
||||
let hero = hero.clone();
|
||||
|
||||
|
@ -100,7 +100,7 @@ impl<A: Ability + 'static> AbilityPage<A> {
|
|||
|
||||
// addons
|
||||
let addons_mode = PageContent::<A, _>::new(
|
||||
Content::new(&engine, reference.clone(), {
|
||||
Content::new::<_, Self>(&engine, reference.clone(), {
|
||||
let engine = engine.clone();
|
||||
let hero = hero.clone();
|
||||
|
||||
|
|
|
@ -32,13 +32,14 @@ pub struct Content<A: Ability + 'static, T: Send + Sync> {
|
|||
}
|
||||
|
||||
impl<A: Ability + 'static, T: Send + Sync> Content<A, T> {
|
||||
pub fn new<F>(
|
||||
pub fn new<F, P>(
|
||||
engine: &Arc<Engine>,
|
||||
reference: Weak<CharacterWindow>,
|
||||
on_enable: F,
|
||||
) -> Result<Self>
|
||||
where
|
||||
F: Fn() -> Result<Vec<T>> + Send + Sync + 'static,
|
||||
P: Page,
|
||||
{
|
||||
let base = GuiSnippet::from_str(
|
||||
engine.gui_handler(),
|
||||
|
@ -48,9 +49,38 @@ impl<A: Ability + 'static, T: Send + Sync> Content<A, T> {
|
|||
let left: Arc<Button> = base.element("left")?;
|
||||
left.set_text("<")?;
|
||||
left.set_info_icon(&engine.controller_icon(ControllerButton::LeftTrigger)?)?;
|
||||
left.set_callback({
|
||||
let reference = reference.clone();
|
||||
|
||||
move || {
|
||||
if let Some(window) = reference.upgrade() {
|
||||
let mut tab = window.tab_mut();
|
||||
let page = tab.downcast_mut::<P>();
|
||||
|
||||
page.previous_tab()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
|
||||
let right: Arc<Button> = base.element("right")?;
|
||||
right.set_text(">")?;
|
||||
right.set_info_icon(&engine.controller_icon(ControllerButton::RightTrigger)?)?;
|
||||
right.set_callback({
|
||||
let reference = reference.clone();
|
||||
|
||||
move || {
|
||||
if let Some(window) = reference.upgrade() {
|
||||
let mut tab = window.tab_mut();
|
||||
let page = tab.downcast_mut::<P>();
|
||||
|
||||
page.next_tab()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
reference,
|
||||
|
|
|
@ -58,7 +58,7 @@ impl<A: Ability + 'static> InventoryPage<A> {
|
|||
|
||||
// items
|
||||
let item_mode = PageContent::<A, _>::new(
|
||||
Content::new(engine, reference.clone(), {
|
||||
Content::new::<_, Self>(engine, reference.clone(), {
|
||||
let engine = engine.clone();
|
||||
let hero = hero.clone();
|
||||
|
||||
|
@ -107,7 +107,7 @@ impl<A: Ability + 'static> InventoryPage<A> {
|
|||
|
||||
// jewels
|
||||
let jewel_mode = PageContent::<A, _>::new(
|
||||
Content::new(engine, reference.clone(), {
|
||||
Content::new::<_, Self>(engine, reference.clone(), {
|
||||
let engine = engine.clone();
|
||||
let hero = hero.clone();
|
||||
|
||||
|
@ -153,7 +153,7 @@ impl<A: Ability + 'static> InventoryPage<A> {
|
|||
|
||||
// maps
|
||||
let map_mode = PageContent::<A, _>::new(
|
||||
Content::new(engine, reference.clone(), {
|
||||
Content::new::<_, Self>(engine, reference.clone(), {
|
||||
let engine = engine.clone();
|
||||
let hero: Entity = hero.clone();
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ mod page_content;
|
|||
mod traits;
|
||||
|
||||
use anyhow::Result;
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use engine::prelude::*;
|
||||
use rpg_components::{
|
||||
components::{
|
||||
|
@ -18,7 +19,6 @@ use rpg_components::{
|
|||
use std::{
|
||||
any::Any,
|
||||
collections::HashMap,
|
||||
mem::transmute,
|
||||
ops::{Deref, DerefMut},
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
|
@ -28,7 +28,7 @@ use std::{
|
|||
|
||||
use self::{abilities::AbilityPage, character::CharacterPage, inventory::InventoryPage};
|
||||
|
||||
trait Page: Any + Send + Sync {
|
||||
trait Page: Any + Send + Sync + Downcast {
|
||||
fn enable(&mut self) -> Result<Arc<Grid>>;
|
||||
fn disable(&mut self) -> Result<()>;
|
||||
fn select(&self) -> Result<()>;
|
||||
|
@ -37,6 +37,8 @@ trait Page: Any + Send + Sync {
|
|||
fn event(&mut self, button: ControllerButton) -> Result<bool>;
|
||||
}
|
||||
|
||||
impl_downcast!(Page);
|
||||
|
||||
struct Tab<'a> {
|
||||
index: usize,
|
||||
tabs: RwLockReadGuard<'a, [Box<dyn Page>; 3]>,
|
||||
|
@ -55,6 +57,12 @@ struct TabMut<'a> {
|
|||
tabs: RwLockWriteGuard<'a, [Box<dyn Page>; 3]>,
|
||||
}
|
||||
|
||||
impl<'a> TabMut<'a> {
|
||||
pub fn downcast_mut<T: Page>(&mut self) -> &mut T {
|
||||
self.tabs[self.index].downcast_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for TabMut<'a> {
|
||||
type Target = Box<dyn Page>;
|
||||
|
||||
|
@ -75,25 +83,16 @@ pub struct Tabs<'a> {
|
|||
|
||||
#[allow(unused)]
|
||||
impl<'a> Tabs<'a> {
|
||||
pub fn character(&mut self) -> &'a CharacterPage {
|
||||
Self::downcast_unchecked(&self.tabs[0])
|
||||
pub fn character(&mut self) -> &CharacterPage {
|
||||
self.tabs[0].downcast_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn inventory<A: Ability + 'static>(&mut self) -> &'a InventoryPage<A> {
|
||||
Self::downcast_unchecked(&self.tabs[1])
|
||||
pub fn inventory<A: Ability + 'static>(&mut self) -> &InventoryPage<A> {
|
||||
self.tabs[1].downcast_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn abilities<A: Ability + 'static>(&mut self) -> &'a AbilityPage<A> {
|
||||
Self::downcast_unchecked(&self.tabs[2])
|
||||
}
|
||||
|
||||
fn downcast_unchecked<T: Page>(boxed_ref: &Box<dyn Page>) -> &'a T {
|
||||
unsafe {
|
||||
let ptr_to_ptr: *const *const T =
|
||||
transmute(destructure_traitobject::data(boxed_ref as *const _));
|
||||
|
||||
&**ptr_to_ptr
|
||||
}
|
||||
pub fn abilities<A: Ability + 'static>(&mut self) -> &AbilityPage<A> {
|
||||
self.tabs[2].downcast_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,25 +102,16 @@ pub struct TabsMut<'a> {
|
|||
|
||||
#[allow(unused)]
|
||||
impl<'a> TabsMut<'a> {
|
||||
pub fn character(&mut self) -> &'a mut CharacterPage {
|
||||
Self::downcast_mut_unchecked(&mut self.tabs[0])
|
||||
pub fn character(&mut self) -> &mut CharacterPage {
|
||||
self.tabs[0].downcast_mut().unwrap()
|
||||
}
|
||||
|
||||
pub fn inventory<A: Ability + 'static>(&mut self) -> &'a mut InventoryPage<A> {
|
||||
Self::downcast_mut_unchecked(&mut self.tabs[1])
|
||||
pub fn inventory<A: Ability + 'static>(&mut self) -> &mut InventoryPage<A> {
|
||||
self.tabs[1].downcast_mut().unwrap()
|
||||
}
|
||||
|
||||
pub fn abilities<A: Ability + 'static>(&mut self) -> &'a mut AbilityPage<A> {
|
||||
Self::downcast_mut_unchecked(&mut self.tabs[2])
|
||||
}
|
||||
|
||||
fn downcast_mut_unchecked<T: Page>(boxed_ref: &mut Box<dyn Page>) -> &'a mut T {
|
||||
unsafe {
|
||||
let ptr_to_ptr: *mut *mut T =
|
||||
transmute(destructure_traitobject::data(boxed_ref as *mut _));
|
||||
|
||||
&mut **ptr_to_ptr
|
||||
}
|
||||
pub fn abilities<A: Ability + 'static>(&mut self) -> &mut AbilityPage<A> {
|
||||
self.tabs[2].downcast_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue