rpg_base/character_window/src/abilities/mod.rs

288 lines
8 KiB
Rust
Raw Normal View History

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> {
2025-03-05 08:45:39 +00:00
fn enable(&mut self, world: &mut World) -> Result<Arc<Grid>> {
2025-02-28 07:43:35 +00:00
println!("enable AbilityPage");
for mode in self.modes.iter_mut() {
mode.content_mut().refresh()?;
}
self.update_page()?;
Ok(self.grid.clone())
}
2025-03-05 08:45:39 +00:00
fn disable(&mut self, world: &mut World) -> Result<()> {
2025-02-28 07:43:35 +00:00
Ok(())
}
2025-03-05 08:45:39 +00:00
fn select(&self, world: &mut World) -> Result<()> {
2025-02-28 07:43:35 +00:00
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(())
}
2025-03-05 08:45:39 +00:00
fn next_tab(&mut self, world: &mut World) -> Result<()> {
2025-02-28 07:43:35 +00:00
self.modes[self.current_mode]
.content_mut()
.next_tab(&self.engine, self.hero)
}
2025-03-05 08:45:39 +00:00
fn previous_tab(&mut self, world: &mut World) -> Result<()> {
2025-02-28 07:43:35 +00:00
self.modes[self.current_mode]
.content_mut()
.previous_tab(&self.engine, self.hero)
}
2025-03-05 08:45:39 +00:00
fn event(&mut self, world: &mut World, button: ControllerButton) -> Result<bool> {
2025-02-28 07:43:35 +00:00
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,
})
}
}