2025-02-28 07:43:35 +00:00
|
|
|
mod ability_right_side;
|
|
|
|
mod content;
|
|
|
|
|
|
|
|
use std::sync::{Arc, Weak};
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
use rpg_components::components::inventory::Inventory;
|
|
|
|
|
|
|
|
use self::ability_right_side::AbilityPageRightSide;
|
|
|
|
|
|
|
|
use super::{
|
2025-03-04 17:40:56 +00:00
|
|
|
CharacterWindow, Page,
|
2025-02-28 07:43:35 +00:00
|
|
|
content::Content,
|
|
|
|
page_content::{EmptyRightSide, PageContent},
|
|
|
|
traits::{PageContentWrapper, RightSide},
|
|
|
|
};
|
|
|
|
use crate::*;
|
|
|
|
|
|
|
|
pub struct AbilityPage<A: Ability + 'static> {
|
|
|
|
close: Weak<Button>,
|
|
|
|
|
|
|
|
engine: Arc<Engine>,
|
|
|
|
hero: Entity,
|
|
|
|
|
|
|
|
grid: Arc<Grid>,
|
|
|
|
|
|
|
|
tooltip: Arc<Grid>,
|
|
|
|
content: Arc<Grid>,
|
|
|
|
|
|
|
|
modes: [Box<dyn PageContentWrapper>; 2],
|
|
|
|
|
|
|
|
current_mode: usize,
|
|
|
|
|
|
|
|
right_side: AbilityPageRightSide<A>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<A: Ability + 'static> AbilityPage<A> {
|
|
|
|
pub fn new(
|
2025-03-04 17:40:56 +00:00
|
|
|
world: &mut World,
|
2025-02-28 07:43:35 +00:00
|
|
|
hero: Entity,
|
|
|
|
reference: Weak<CharacterWindow>,
|
|
|
|
close: &Arc<Button>,
|
|
|
|
) -> Result<Self> {
|
2025-03-04 17:40:56 +00:00
|
|
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
|
|
|
let grid = Grid::new(gui_handler, 2, 1, false)?;
|
2025-02-28 07:43:35 +00:00
|
|
|
|
|
|
|
let left_base = GuiSnippet::from_str(
|
2025-03-04 17:40:56 +00:00
|
|
|
gui_handler,
|
2025-02-28 07:43:35 +00:00
|
|
|
include_str!("../../resources/abilities/left_side.xml"),
|
|
|
|
)?;
|
2025-03-04 17:40:56 +00:00
|
|
|
grid.attach(gui_handler, left_base.clone(), 0, 0, 1, 1)?;
|
2025-02-28 07:43:35 +00:00
|
|
|
|
|
|
|
Self::setup_content_switch(&left_base, reference.clone())?;
|
|
|
|
|
|
|
|
let tooltip = left_base.element("tooltip")?;
|
|
|
|
let content = left_base.element("content")?;
|
|
|
|
|
|
|
|
// abilities
|
|
|
|
let ability_mode = PageContent::new(
|
|
|
|
Content::new::<_, Self>(&engine, reference.clone(), {
|
|
|
|
let engine = engine.clone();
|
|
|
|
let hero = hero.clone();
|
|
|
|
|
|
|
|
move || {
|
|
|
|
let mut data = Vec::new();
|
|
|
|
|
|
|
|
engine.on_scene(|scene| {
|
|
|
|
let hero_object = scene.entity(hero)?;
|
|
|
|
let inventory = hero_object.get_component::<Inventory<A>>()?;
|
|
|
|
|
|
|
|
data = inventory.iter_books().cloned().collect();
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(data)
|
|
|
|
}
|
|
|
|
})?,
|
|
|
|
{
|
|
|
|
let ui = GuiSnippet::from_str(
|
|
|
|
engine.gui_handler(),
|
|
|
|
include_str!("../../resources/abilities/ability_tooltip.xml"),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
let equip: Arc<Label> = ui.element("equip")?;
|
|
|
|
equip.set_info_icon(&engine.controller_icon(ControllerButton::A)?)?;
|
|
|
|
|
|
|
|
let upgrade: Arc<Label> = ui.element("upgrade")?;
|
|
|
|
upgrade.set_info_icon(&engine.controller_icon(ControllerButton::Y)?)?;
|
|
|
|
|
|
|
|
let salvage: Arc<Label> = ui.element("salvage")?;
|
|
|
|
salvage.set_info_icon(&engine.controller_icon(ControllerButton::X)?)?;
|
|
|
|
|
|
|
|
let switch_mode: Arc<Label> = ui.element("switch_mode")?;
|
|
|
|
switch_mode.set_info_icon(&engine.controller_icon(ControllerButton::LeftStick)?)?;
|
|
|
|
|
|
|
|
ui
|
|
|
|
},
|
|
|
|
EmptyRightSide,
|
|
|
|
);
|
|
|
|
|
|
|
|
// addons
|
|
|
|
let addons_mode = PageContent::<A, _>::new(
|
|
|
|
Content::new::<_, Self>(&engine, reference.clone(), {
|
|
|
|
let engine = engine.clone();
|
|
|
|
let hero = hero.clone();
|
|
|
|
|
|
|
|
move || {
|
|
|
|
let mut data = Vec::new();
|
|
|
|
|
|
|
|
engine.on_scene(|scene| {
|
|
|
|
let hero_object = scene.entity(hero)?;
|
|
|
|
let inventory = hero_object.get_component::<Inventory<A>>()?;
|
|
|
|
|
|
|
|
data = inventory.iter_addons().cloned().collect();
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(data)
|
|
|
|
}
|
|
|
|
})?,
|
|
|
|
{
|
|
|
|
let ui = GuiSnippet::from_str(
|
|
|
|
engine.gui_handler(),
|
|
|
|
include_str!("../../resources/abilities/addon_tooltip.xml"),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
let equip: Arc<Label> = ui.element("socket")?;
|
|
|
|
equip.set_info_icon(&engine.controller_icon(ControllerButton::A)?)?;
|
|
|
|
|
|
|
|
let salvage: Arc<Label> = ui.element("salvage")?;
|
|
|
|
salvage.set_info_icon(&engine.controller_icon(ControllerButton::X)?)?;
|
|
|
|
|
|
|
|
let switch_mode: Arc<Label> = ui.element("switch_mode")?;
|
|
|
|
switch_mode.set_info_icon(&engine.controller_icon(ControllerButton::LeftStick)?)?;
|
|
|
|
|
|
|
|
ui
|
|
|
|
},
|
|
|
|
EmptyRightSide,
|
|
|
|
);
|
|
|
|
|
|
|
|
let right_side = AbilityPageRightSide::new(&engine, &reference, hero)?;
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
close: Arc::downgrade(close),
|
|
|
|
|
|
|
|
engine: engine.clone(),
|
|
|
|
hero,
|
|
|
|
|
|
|
|
grid,
|
|
|
|
|
|
|
|
tooltip,
|
|
|
|
content,
|
|
|
|
|
|
|
|
modes: [Box::new(ability_mode), Box::new(addons_mode)],
|
|
|
|
|
|
|
|
current_mode: 0,
|
|
|
|
|
|
|
|
right_side,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn update_page(&mut self) -> Result<()> {
|
|
|
|
match self.current_mode {
|
|
|
|
0 => println!("update ability view"),
|
|
|
|
1 => println!("update addon view"),
|
|
|
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
|
|
|
|
let mode = &mut self.modes[self.current_mode];
|
|
|
|
mode.content_mut().update(&self.engine, self.hero)?;
|
|
|
|
|
|
|
|
self.tooltip.attach(mode.tooltip().clone(), 0, 0, 1, 1)?;
|
|
|
|
self.content
|
|
|
|
.attach(mode.content_mut().base().clone(), 0, 0, 1, 1)?;
|
|
|
|
|
|
|
|
self.right_side.refresh(&self.engine, self.hero)?;
|
|
|
|
self.grid
|
|
|
|
.attach(self.right_side.base().clone(), 1, 0, 1, 1)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setup_content_switch(
|
|
|
|
left_base: &GuiSnippet,
|
|
|
|
reference: Weak<CharacterWindow>,
|
|
|
|
) -> Result<()> {
|
|
|
|
let switch = {
|
|
|
|
let reference = reference.clone();
|
|
|
|
|
|
|
|
move |index| {
|
|
|
|
if let Some(menu) = reference.upgrade() {
|
|
|
|
let mut tabs = menu.tabs_mut();
|
|
|
|
let me = tabs.abilities::<A>();
|
|
|
|
|
|
|
|
if me.current_mode != index {
|
|
|
|
me.current_mode = index;
|
|
|
|
me.update_page()?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let switch_to_abilities = Box::new({
|
|
|
|
let switch = switch.clone();
|
|
|
|
|
|
|
|
move || switch(0)
|
|
|
|
});
|
|
|
|
|
|
|
|
let switch_to_addons = Box::new({
|
|
|
|
let switch = switch.clone();
|
|
|
|
|
|
|
|
move || switch(1)
|
|
|
|
});
|
|
|
|
|
|
|
|
left_base.set_click_callbacks(vec![
|
|
|
|
("abilities", switch_to_abilities),
|
|
|
|
("addons", switch_to_addons),
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<A: Ability + 'static> Page for AbilityPage<A> {
|
|
|
|
fn enable(&mut self) -> Result<Arc<Grid>> {
|
|
|
|
println!("enable AbilityPage");
|
|
|
|
|
|
|
|
for mode in self.modes.iter_mut() {
|
|
|
|
mode.content_mut().refresh()?;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.update_page()?;
|
|
|
|
|
|
|
|
Ok(self.grid.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn disable(&mut self) -> Result<()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn select(&self) -> Result<()> {
|
|
|
|
let mode = &self.modes[self.current_mode];
|
|
|
|
|
|
|
|
mode.content().select()?;
|
|
|
|
|
|
|
|
if mode.content().is_empty() {
|
|
|
|
if let Some(close) = self.close.upgrade() {
|
|
|
|
close.select()?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn next_tab(&mut self) -> Result<()> {
|
|
|
|
self.modes[self.current_mode]
|
|
|
|
.content_mut()
|
|
|
|
.next_tab(&self.engine, self.hero)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn previous_tab(&mut self) -> Result<()> {
|
|
|
|
self.modes[self.current_mode]
|
|
|
|
.content_mut()
|
|
|
|
.previous_tab(&self.engine, self.hero)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn event(&mut self, button: ControllerButton) -> Result<bool> {
|
|
|
|
Ok(match button {
|
|
|
|
ControllerButton::LeftStick => {
|
|
|
|
self.current_mode = (self.current_mode + 1) % self.modes.len();
|
|
|
|
self.update_page()?;
|
|
|
|
self.select()?;
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
ControllerButton::RightStick => {
|
|
|
|
self.right_side.next_ability(&self.engine, self.hero)?;
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => false,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|