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