273 lines
9.7 KiB
Rust
273 lines
9.7 KiB
Rust
use std::marker::PhantomData;
|
|
use std::sync::{Arc, Weak};
|
|
|
|
use rpg_components::components::ability_slots::AbilitySlots;
|
|
use rpg_components::components::crafting_materials::CraftingMaterials;
|
|
use rpg_components::components::inventory::Storable;
|
|
use rpg_components::components::statistics::Statistics;
|
|
use rpg_components::config::items::ItemSettings;
|
|
use rpg_components::items::Rarities;
|
|
|
|
use crate::*;
|
|
|
|
use crate::{traits::RightSide, CharacterWindow};
|
|
|
|
pub struct AbilityPageRightSide<A: Ability + 'static> {
|
|
snippet: Arc<GuiSnippet>,
|
|
|
|
ability_index: usize,
|
|
|
|
ability_marker: PhantomData<A>,
|
|
}
|
|
|
|
impl<A: Ability + 'static> AbilityPageRightSide<A> {
|
|
const ABILITY_BUTTON_NAMES: [&'static str; 4] = [
|
|
"first_ability",
|
|
"second_ability",
|
|
"third_ability",
|
|
"fourth_ability",
|
|
];
|
|
|
|
pub fn new(
|
|
engine: &Arc<Engine>,
|
|
reference: &Weak<CharacterWindow>,
|
|
hero: Entity,
|
|
) -> Result<Self> {
|
|
let snippet = GuiSnippet::from_str(
|
|
engine.gui_handler(),
|
|
include_str!("../../resources/abilities/right_side.xml"),
|
|
)?;
|
|
|
|
let color_settings = &engine
|
|
.scene()
|
|
.resources
|
|
.get::<ItemSettings>()
|
|
.rarity_color_settings;
|
|
|
|
Self::rarity_icon_background(&snippet, "common", color_settings.common)?;
|
|
Self::rarity_icon_background(&snippet, "uncommon", color_settings.uncommon)?;
|
|
Self::rarity_icon_background(&snippet, "magical", color_settings.magical)?;
|
|
Self::rarity_icon_background(&snippet, "rare", color_settings.rare)?;
|
|
Self::rarity_icon_background(&snippet, "epic", color_settings.epic)?;
|
|
Self::rarity_icon_background(&snippet, "legendary", color_settings.legendary)?;
|
|
|
|
for (index, name) in Self::ABILITY_BUTTON_NAMES.iter().enumerate() {
|
|
let button: Arc<Button> = snippet.element(name)?;
|
|
|
|
button.set_info_icon(&engine.controller_icon(ControllerButton::RightStick)?)?;
|
|
|
|
button.set_callback({
|
|
let reference = reference.clone();
|
|
|
|
move || {
|
|
if let Some(menu) = reference.upgrade() {
|
|
let mut tabs = menu.tabs_mut();
|
|
let abilities = tabs.abilities::<A>();
|
|
|
|
abilities.right_side.ability_index = index;
|
|
abilities.update_page()?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
});
|
|
|
|
button.set_select_callback({
|
|
let engine = engine.clone();
|
|
let reference = reference.clone();
|
|
let weak_button = Arc::downgrade(&button);
|
|
|
|
move |selected| {
|
|
if let Some(menu) = reference.upgrade() {
|
|
if selected {
|
|
engine.on_scene(|scene| {
|
|
let entity = scene.entity(hero)?;
|
|
let abilities = entity.get_component::<AbilitySlots<A>>()?;
|
|
|
|
if let Some(book) = abilities.book(index) {
|
|
let button = weak_button.upgrade().unwrap();
|
|
let button_pos = button.position_extent();
|
|
|
|
let target_x = button_pos.0 + button_pos.2 as i32;
|
|
let target_y = button_pos.1;
|
|
|
|
let statistics = entity.get_component::<Statistics>()?;
|
|
|
|
let gui = book.create_tooltip(
|
|
engine.gui_handler(),
|
|
statistics,
|
|
(target_x, target_y),
|
|
)?;
|
|
gui.enable()?;
|
|
gui.perform_single_check(button_pos.0, button_pos.1)?;
|
|
|
|
menu.add_tooltip("active_ability", gui);
|
|
}
|
|
|
|
Ok(())
|
|
})?;
|
|
} else {
|
|
menu.remove_tooltip("active_ability");
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
});
|
|
|
|
button.set_custom_callback({
|
|
let engine = engine.clone();
|
|
let reference = reference.clone();
|
|
|
|
move |button| match button {
|
|
ControllerButton::Y => {
|
|
engine.on_scene_mut(|scene| {
|
|
let entity = scene.entity_mut(hero)?;
|
|
let mut multi_mut = entity.multi_mut();
|
|
|
|
let abilities = multi_mut.get::<AbilitySlots<A>>()?;
|
|
|
|
if let Some(ability) = abilities.book_mut(index) {
|
|
let materials = multi_mut.get::<CraftingMaterials>()?;
|
|
|
|
ability.upgrade(materials);
|
|
|
|
if let Some(menu) = reference.upgrade() {
|
|
menu.tabs_mut()
|
|
.abilities::<A>()
|
|
.right_side
|
|
.refresh(&engine, hero)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
})?;
|
|
|
|
Ok(true)
|
|
}
|
|
|
|
_ => Ok(false),
|
|
}
|
|
})
|
|
}
|
|
|
|
Ok(Self {
|
|
snippet,
|
|
ability_index: 0,
|
|
ability_marker: PhantomData,
|
|
})
|
|
}
|
|
|
|
pub fn selected_ability(&self) -> usize {
|
|
self.ability_index
|
|
}
|
|
|
|
fn rarity_icon_background(gui: &GuiSnippet, element: &str, color: Color) -> Result<()> {
|
|
let icon: Arc<Icon> = gui.element(element)?;
|
|
|
|
icon.set_background(FillTypeInfo::Element(
|
|
ElementDescriptor::new(color, Color::Black, 2),
|
|
DisplayableFillType::Square,
|
|
))
|
|
}
|
|
|
|
fn update_crafting_count(&self, element: &str, value: u32) -> Result<()> {
|
|
let icon: Arc<Icon> = self.snippet.element(element)?;
|
|
icon.set_text(value)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn update_ability_icon(&self, element: &str, image: Option<Arc<Image>>) -> Result<()> {
|
|
let button: Arc<Button> = self.snippet.element(element)?;
|
|
|
|
match image {
|
|
Some(image) => {
|
|
button.set_icon(&image)?;
|
|
}
|
|
None => {
|
|
button.clear_icon()?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn update_active_ability(&self, engine: &Engine, abilities: &AbilitySlots<A>) -> Result<()> {
|
|
let grid: Arc<Grid> = self.snippet.element("ability_content")?;
|
|
let (_, rows) = grid.dimensions();
|
|
|
|
for y in 0..rows {
|
|
grid.detach(0, y)?;
|
|
}
|
|
|
|
if let Some(ability) = abilities.book(self.ability_index) {
|
|
for (index, addon) in ability.addons().iter().enumerate() {
|
|
match addon.as_ref() {
|
|
Some(addon) => {
|
|
let addon_type_snippet = GuiSnippet::from_str(
|
|
engine.gui_handler(),
|
|
include_str!("../../resources/abilities/addon_type_snippet.xml"),
|
|
)?;
|
|
|
|
let addon_icon: Arc<Icon> = addon_type_snippet.element("addon_icon")?;
|
|
let addon_type: Arc<Label> = addon_type_snippet.element("addon_type")?;
|
|
let addon_value: Arc<Label> = addon_type_snippet.element("addon_value")?;
|
|
|
|
addon_icon.set_icon(&addon.icon())?;
|
|
addon_type.set_text(&format!("{}", addon.addon_type()))?;
|
|
addon_value.set_text(&addon.addon_type().val_as_str())?;
|
|
|
|
grid.attach(addon_type_snippet, 0, index, 1, 1)?;
|
|
}
|
|
None => {
|
|
let empty_addon = GuiSnippet::from_str(
|
|
engine.gui_handler(),
|
|
include_str!("../../resources/abilities/empty_addon_snippet.xml"),
|
|
)?;
|
|
|
|
grid.attach(empty_addon, 0, index, 1, 1)?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn next_ability(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()> {
|
|
self.ability_index = (self.ability_index + 1) % 4;
|
|
self.refresh(engine, hero)
|
|
}
|
|
}
|
|
|
|
impl<A: Ability + 'static> RightSide for AbilityPageRightSide<A> {
|
|
fn refresh(&mut self, engine: &Engine, hero: Entity) -> Result<()> {
|
|
engine.on_scene(|scene| {
|
|
let entity = scene.entity(hero)?;
|
|
|
|
let crafting = entity.get_component::<CraftingMaterials>()?;
|
|
|
|
self.update_crafting_count("common", crafting.count(Rarities::Common))?;
|
|
self.update_crafting_count("uncommon", crafting.count(Rarities::Uncommon))?;
|
|
self.update_crafting_count("magical", crafting.count(Rarities::Magical))?;
|
|
self.update_crafting_count("rare", crafting.count(Rarities::Rare))?;
|
|
self.update_crafting_count("epic", crafting.count(Rarities::Epic))?;
|
|
self.update_crafting_count("legendary", crafting.count(Rarities::Legendary))?;
|
|
|
|
let abilities = entity.get_component::<AbilitySlots<A>>()?;
|
|
|
|
for (index, name) in Self::ABILITY_BUTTON_NAMES.iter().enumerate() {
|
|
self.update_ability_icon(name, abilities.book(index).map(|book| book.icon()))?;
|
|
}
|
|
|
|
self.update_active_ability(engine, abilities)?;
|
|
|
|
Ok(())
|
|
})
|
|
}
|
|
|
|
fn base(&self) -> &Arc<GuiSnippet> {
|
|
&self.snippet
|
|
}
|
|
}
|