Fix majority of item tab

This commit is contained in:
Michael Hübner 2025-03-05 09:45:39 +01:00
parent 5de2c86f09
commit 0ed03f16af
17 changed files with 760 additions and 796 deletions

View file

@ -11,3 +11,4 @@ downcast-rs = { workspace = true }
engine = { workspace = true }
rpg_components = { path = "../rpg_components" }
assetpath.workspace = true

View file

@ -225,7 +225,7 @@ impl<A: Ability + 'static> AbilityPage<A> {
}
impl<A: Ability + 'static> Page for AbilityPage<A> {
fn enable(&mut self) -> Result<Arc<Grid>> {
fn enable(&mut self, world: &mut World) -> Result<Arc<Grid>> {
println!("enable AbilityPage");
for mode in self.modes.iter_mut() {
@ -237,11 +237,11 @@ impl<A: Ability + 'static> Page for AbilityPage<A> {
Ok(self.grid.clone())
}
fn disable(&mut self) -> Result<()> {
fn disable(&mut self, world: &mut World) -> Result<()> {
Ok(())
}
fn select(&self) -> Result<()> {
fn select(&self, world: &mut World) -> Result<()> {
let mode = &self.modes[self.current_mode];
mode.content().select()?;
@ -255,19 +255,19 @@ impl<A: Ability + 'static> Page for AbilityPage<A> {
Ok(())
}
fn next_tab(&mut self) -> Result<()> {
fn next_tab(&mut self, world: &mut World) -> Result<()> {
self.modes[self.current_mode]
.content_mut()
.next_tab(&self.engine, self.hero)
}
fn previous_tab(&mut self) -> Result<()> {
fn previous_tab(&mut self, world: &mut World) -> Result<()> {
self.modes[self.current_mode]
.content_mut()
.previous_tab(&self.engine, self.hero)
}
fn event(&mut self, button: ControllerButton) -> Result<bool> {
fn event(&mut self, world: &mut World, button: ControllerButton) -> Result<bool> {
Ok(match button {
ControllerButton::LeftStick => {
self.current_mode = (self.current_mode + 1) % self.modes.len();

View file

@ -43,7 +43,7 @@ impl CharacterPage {
strength.set_callback({
let update_stats = Self::create_update_stats(hero, engine, reference);
move || {
move |_world| {
update_stats(|attributes| {
attributes.add_strength(Strength::from(1));
})
@ -54,7 +54,7 @@ impl CharacterPage {
agility.set_callback({
let update_stats = Self::create_update_stats(hero, engine, reference);
move || {
move |_world| {
update_stats(|attributes| {
attributes.add_agility(Agility::from(1));
})
@ -65,7 +65,7 @@ impl CharacterPage {
intelligence.set_callback({
let update_stats = Self::create_update_stats(hero, engine, reference);
move || {
move |_world| {
update_stats(|attributes| {
attributes.add_intelligence(Intelligence::from(1));
})
@ -80,14 +80,14 @@ impl CharacterPage {
})
}
fn refresh(&self) -> Result<()> {
self.update_stats()?;
self.update_attributes()?;
fn refresh(&self, world: &mut World) -> Result<()> {
self.update_stats(world)?;
self.update_attributes(world)?;
Ok(())
}
fn update_stats(&self, world: &World) -> Result<()> {
fn update_stats(&self, world: &mut World) -> Result<()> {
let air_def: Arc<Label> = self.snippet.element("air_def_info")?;
let fire_def: Arc<Label> = self.snippet.element("fire_def_info")?;
let water_def: Arc<Label> = self.snippet.element("water_def_info")?;
@ -109,26 +109,46 @@ impl CharacterPage {
let entity = world.entity(self.hero)?;
let statistics = entity.get_component::<Statistics>()?;
air_def.set_text(&format!("{}", statistics.air_resistance.raw()))?;
fire_def.set_text(&format!("{}", statistics.fire_resistance.raw()))?;
water_def.set_text(&format!("{}", statistics.water_resistance.raw()))?;
armor.set_text(&format!("{}", statistics.armor.raw()))?;
let gui_handler = world.resources.get_mut::<GuiHandler>();
air_dmg.set_text(&format!("{}", statistics.air_damage.raw()))?;
fire_dmg.set_text(&format!("{}", statistics.fire_damage.raw()))?;
water_dmg.set_text(&format!("{}", statistics.water_damage.raw()))?;
phys_dmg.set_text(&format!("{}", statistics.physical_damage.raw()))?;
air_def.set_text(gui_handler, &format!("{}", statistics.air_resistance.raw()))?;
fire_def.set_text(
gui_handler,
&format!("{}", statistics.fire_resistance.raw()),
)?;
water_def.set_text(
gui_handler,
&format!("{}", statistics.water_resistance.raw()),
)?;
armor.set_text(gui_handler, &format!("{}", statistics.armor.raw()))?;
crit_chance.set_text(&format!("{:.2} %", statistics.critical_hit_chance.raw()))?;
crit_dmg.set_text(&format!(
"{:.2} %",
statistics.critical_hit_damage.raw() + 100.0
))?;
air_dmg.set_text(gui_handler, &format!("{}", statistics.air_damage.raw()))?;
fire_dmg.set_text(gui_handler, &format!("{}", statistics.fire_damage.raw()))?;
water_dmg.set_text(gui_handler, &format!("{}", statistics.water_damage.raw()))?;
phys_dmg.set_text(
gui_handler,
&format!("{}", statistics.physical_damage.raw()),
)?;
health.set_text(&format!("{:.0}", statistics.health.raw()))?;
health_regen.set_text(&format!("{:.2}", statistics.health_regeneration.raw()))?;
mana.set_text(&format!("{:.0}", statistics.mana.raw()))?;
mana_regen.set_text(&format!("{:.2}", statistics.mana_regeneration.raw()))?;
crit_chance.set_text(
gui_handler,
&format!("{:.2} %", statistics.critical_hit_chance.raw()),
)?;
crit_dmg.set_text(
gui_handler,
&format!("{:.2} %", statistics.critical_hit_damage.raw() + 100.0),
)?;
health.set_text(gui_handler, &format!("{:.0}", statistics.health.raw()))?;
health_regen.set_text(
gui_handler,
&format!("{:.2}", statistics.health_regeneration.raw()),
)?;
mana.set_text(gui_handler, &format!("{:.0}", statistics.mana.raw()))?;
mana_regen.set_text(
gui_handler,
&format!("{:.2}", statistics.mana_regeneration.raw()),
)?;
Ok(())
}
@ -147,24 +167,29 @@ impl CharacterPage {
let level = entity.get_component::<Level>()?;
let attributes = entity.get_component::<Attributes>()?;
level_label.set_text(format!("Level: {}", level.level()))?;
level_progress.set_text(format!(
"{} / {}",
level.current_experience, level.experience_needed
))?;
let gui_handler = world.resources.get_mut::<GuiHandler>();
attributes_label.set_text(format!(
"Attributes ({})",
Self::available_attribute_points(
world.resources.get::<AttributeSettings>(),
attributes,
level
)
))?;
level_label.set_text(gui_handler, format!("Level: {}", level.level()))?;
level_progress.set_text(
gui_handler,
format!("{} / {}", level.current_experience, level.experience_needed),
)?;
strength.set_text(attributes.strength().raw())?;
agility.set_text(attributes.agility().raw())?;
intelligence.set_text(attributes.intelligence().raw())?;
attributes_label.set_text(
gui_handler,
format!(
"Attributes ({})",
Self::available_attribute_points(
world.resources.get::<AttributeSettings>(),
attributes,
level
)
),
)?;
strength.set_text(gui_handler, attributes.strength().raw())?;
agility.set_text(gui_handler, attributes.agility().raw())?;
intelligence.set_text(gui_handler, attributes.intelligence().raw())?;
Ok(())
}
@ -185,45 +210,39 @@ impl CharacterPage {
fn create_update_stats<F>(
hero: Entity,
engine: &Arc<Engine>,
reference: &Weak<CharacterWindow>,
) -> impl Fn(F) -> Result<()> + Clone
) -> impl Fn(&mut World, F) -> Result<()> + Clone
where
F: Fn(&mut Attributes),
{
let engine = engine.clone();
let reference = reference.clone();
move |upgrade: F| {
move |world, upgrade: F| {
let mut upgraded = false;
engine.on_scene_mut(|scene| {
let (resources, entity) = scene.entity_resource(hero)?;
let mut multi_mut = entity.multi_mut();
let (resources, entity) = world.entity_resource(hero)?;
let mut multi_mut = entity.multi_mut();
let attribute_settings = resources.get::<AttributeSettings>();
let item_settings = resources.get::<ItemSettings>();
let attribute_settings = resources.get::<AttributeSettings>();
let item_settings = resources.get::<ItemSettings>();
let level = multi_mut.get::<Level>()?;
let attributes = multi_mut.get::<Attributes>()?;
let level = multi_mut.get::<Level>()?;
let attributes = multi_mut.get::<Attributes>()?;
if Self::available_attribute_points(attribute_settings, attributes, level) > 0 {
upgrade(attributes);
if Self::available_attribute_points(attribute_settings, attributes, level) > 0 {
upgrade(attributes);
let statistics = multi_mut.get::<Statistics>()?;
let items = multi_mut.get::<ItemSlotContainer>()?;
let statistics = multi_mut.get::<Statistics>()?;
let items = multi_mut.get::<ItemSlotContainer>()?;
statistics.update(attributes, attribute_settings, (&*items, item_settings));
statistics.update(attributes, attribute_settings, (&*items, item_settings));
upgraded = true;
}
Ok(())
})?;
upgraded = true;
}
if upgraded {
if let Some(menu) = reference.upgrade() {
menu.tabs().character().refresh()?;
menu.tabs().character().refresh(world)?;
}
}
@ -233,7 +252,7 @@ impl CharacterPage {
}
impl Page for CharacterPage {
fn enable(&mut self) -> Result<Arc<Grid>> {
fn enable(&mut self, world: &mut World) -> Result<Arc<Grid>> {
println!("enable CharacterPage");
self.refresh()?;
@ -241,26 +260,26 @@ impl Page for CharacterPage {
Ok(self.grid.clone())
}
fn disable(&mut self) -> Result<()> {
fn disable(&mut self, world: &mut World) -> Result<()> {
Ok(())
}
fn select(&self) -> Result<()> {
fn select(&self, world: &mut World) -> Result<()> {
let strength: Arc<Button> = self.snippet.element("strength_field")?;
strength.select()?;
Ok(())
}
fn next_tab(&mut self) -> Result<()> {
fn next_tab(&mut self, world: &mut World) -> Result<()> {
Ok(())
}
fn previous_tab(&mut self) -> Result<()> {
fn previous_tab(&mut self, world: &mut World) -> Result<()> {
Ok(())
}
fn event(&mut self, _button: ControllerButton) -> Result<bool> {
fn event(&mut self, world: &mut World, _button: ControllerButton) -> Result<bool> {
Ok(false)
}
}

View file

@ -6,16 +6,16 @@ use std::{
use crate::*;
pub trait ContentWrapper: ContentUpdate + Send + Sync {
fn refresh(&mut self) -> Result<()>;
fn next_tab(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()>;
fn previous_tab(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()>;
fn refresh(&mut self, world: &mut World) -> Result<()>;
fn next_tab(&mut self, world: &mut World, hero: Entity) -> Result<()>;
fn previous_tab(&mut self, world: &mut World, hero: Entity) -> Result<()>;
fn base(&self) -> &Arc<GuiSnippet>;
fn is_empty(&self) -> bool;
}
pub trait ContentUpdate {
fn update(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()>;
fn select(&self) -> Result<()>;
fn update(&mut self, world: &mut World, hero: Entity) -> Result<()>;
fn select(&self, world: &mut World) -> Result<()>;
}
pub struct Content<A: Ability + 'static, T: Send + Sync> {
@ -23,7 +23,7 @@ pub struct Content<A: Ability + 'static, T: Send + Sync> {
base: Arc<GuiSnippet>,
data: Vec<T>,
on_enable: Box<dyn Fn() -> Result<Vec<T>> + Send + Sync + 'static>,
on_enable: Box<dyn Fn(&mut World) -> Result<Vec<T>> + Send + Sync + 'static>,
page: usize,
pages: usize,
@ -33,31 +33,36 @@ pub struct Content<A: Ability + 'static, T: Send + Sync> {
impl<A: Ability + 'static, T: Send + Sync> Content<A, T> {
pub fn new<F, P>(
engine: &Arc<Engine>,
world: &mut World,
reference: Weak<CharacterWindow>,
on_enable: F,
) -> Result<Self>
where
F: Fn() -> Result<Vec<T>> + Send + Sync + 'static,
F: Fn(&mut World) -> Result<Vec<T>> + Send + Sync + 'static,
P: Page,
{
let base = GuiSnippet::from_str(
engine.gui_handler(),
include_str!("../resources/content.xml"),
)?;
let base = GuiSnippet::from_str(world, include_str!("../resources/content.xml"))?;
let mut resources = world.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>();
let engine_settings = resources.get::<EngineSettings>();
let context = resources.get::<Context>();
let left: Arc<Button> = base.element("left")?;
left.set_text("<")?;
left.set_info_icon(&engine.controller_icon(ControllerButton::LeftTrigger)?)?;
left.set_text(gui_handler, "<")?;
left.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::LeftTrigger)?,
)?;
left.set_callback({
let reference = reference.clone();
move || {
move |world| {
if let Some(window) = reference.upgrade() {
let mut tab = window.tab_mut();
let page = tab.downcast_mut::<P>();
page.previous_tab()?;
page.previous_tab(world)?;
}
Ok(())
@ -65,17 +70,20 @@ impl<A: Ability + 'static, T: Send + Sync> Content<A, T> {
});
let right: Arc<Button> = base.element("right")?;
right.set_text(">")?;
right.set_info_icon(&engine.controller_icon(ControllerButton::RightTrigger)?)?;
right.set_text(gui_handler, ">")?;
right.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::RightTrigger)?,
)?;
right.set_callback({
let reference = reference.clone();
move || {
move |world| {
if let Some(window) = reference.upgrade() {
let mut tab = window.tab_mut();
let page = tab.downcast_mut::<P>();
page.next_tab()?;
page.next_tab(world)?;
}
Ok(())
@ -96,34 +104,34 @@ impl<A: Ability + 'static, T: Send + Sync> Content<A, T> {
})
}
fn clear_grid(grid: &Arc<Grid>) -> Result<()> {
fn clear_grid(world: &mut World, grid: &Arc<Grid>) -> Result<()> {
let (rows, columns) = grid.dimensions();
for x in 0..columns {
for y in 0..rows {
grid.detach(x, y)?;
grid.detach(world, x, y)?;
}
}
Ok(())
}
fn set_tab(&self, label: &Arc<Label>) -> Result<()> {
label.set_text(format!("{} / {}", self.page + 1, self.pages))
fn set_tab(&self, gui_handler: &mut GuiHandler, label: &Arc<Label>) -> Result<()> {
label.set_text(gui_handler, format!("{} / {}", self.page + 1, self.pages))
}
pub fn update_base<F>(&mut self, engine: &Arc<Engine>, setup: F) -> Result<()>
pub fn update_base<F>(&mut self, world: &mut World, setup: F) -> Result<()>
where
Self: ContentWrapper,
F: Fn(&Arc<Button>, &T, usize) -> Result<()>,
F: Fn(&mut World, &Arc<Button>, &T, usize) -> Result<()>,
{
self.refresh()?;
self.refresh(world)?;
let grid: Arc<Grid> = self.base.element("content")?;
let label: Arc<Label> = self.base.element("tab_info")?;
Self::clear_grid(&grid)?;
self.set_tab(&label)?;
Self::clear_grid(world, &grid)?;
self.set_tab(world.resources.get_mut::<GuiHandler>(), &label)?;
let (rows, columns) = grid.dimensions();
@ -134,13 +142,13 @@ impl<A: Ability + 'static, T: Send + Sync> Content<A, T> {
match self.data.get(index) {
Some(t) => {
let snippet = GuiSnippet::from_str(
engine.gui_handler(),
world,
include_str!("../resources/content_button.xml"),
)?;
let button: Arc<Button> = snippet.element("button")?;
setup(&button, t, index)?;
grid.attach(button, x, y, 1, 1)?;
setup(world, &button, t, index)?;
grid.attach(world, button, x, y, 1, 1)?;
}
None => break 'outer,
}
@ -150,11 +158,16 @@ impl<A: Ability + 'static, T: Send + Sync> Content<A, T> {
Ok(())
}
pub fn select(&self) -> Result<()> {
pub fn select(&self, gui_handler: &mut GuiHandler) -> Result<()> {
let grid: Arc<Grid> = self.base.element("content")?;
if let Some(child) = grid.child_at(0, 0)? {
child.gridable().unwrap().selectable().unwrap().select()?;
child
.gridable()
.unwrap()
.selectable()
.unwrap()
.select(gui_handler)?;
}
Ok(())
@ -165,8 +178,8 @@ impl<A: Ability + 'static, T: Send + Sync> ContentWrapper for Content<A, T>
where
Content<A, T>: ContentUpdate,
{
fn refresh(&mut self) -> Result<()> {
self.data = (self.on_enable)()?;
fn refresh(&mut self, world: &mut World) -> Result<()> {
self.data = (self.on_enable)(world)?;
let grid: Arc<Grid> = self.base.element("content")?;
let (rows, columns) = grid.dimensions();
@ -176,19 +189,19 @@ where
Ok(())
}
fn next_tab(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()> {
fn next_tab(&mut self, world: &mut World, hero: Entity) -> Result<()> {
if self.page < (self.pages - 1) {
self.page += 1;
self.update(engine, hero)?;
self.update(world, hero)?;
}
Ok(())
}
fn previous_tab(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()> {
fn previous_tab(&mut self, world: &mut World, hero: Entity) -> Result<()> {
if self.page > 0 {
self.page -= 1;
self.update(engine, hero)?;
self.update(world, hero)?;
}
Ok(())

View file

@ -11,15 +11,15 @@ use rpg_components::items::{Item, ItemAffix, Jewel, MapItem};
use crate::*;
use crate::{
content::{Content, ContentUpdate},
CharacterWindow,
content::{Content, ContentUpdate},
};
use super::jewel_right_side::{LowerJewels, ReferenceItemSource, ReferenceObject};
impl<A: Ability + 'static> Content<A, Item> {
fn salvage_item(engine: &Arc<Engine>, hero: Entity, item_index: usize) -> Result<()> {
CharacterWindow::salvage_from_inventory::<A, _, _>(engine, hero, |inventory| {
fn salvage_item(world: &mut World, hero: Entity, item_index: usize) -> Result<()> {
CharacterWindow::salvage_from_inventory::<A, _, _>(world, hero, |inventory| {
let mut item = inventory.remove_item(item_index);
// unsocket jewels and add them into inventory
@ -37,157 +37,146 @@ impl<A: Ability + 'static> Content<A, Item> {
})
}
fn select_to_socket(engine: &Arc<Engine>, hero: Entity, item_index: usize) -> Result<bool> {
fn select_to_socket(world: &mut World, hero: Entity, item_index: usize) -> Result<bool> {
let mut has_empty_sockets = true;
engine.on_scene_mut(|scene| {
let entity = scene.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let item = inventory.item_at(item_index).clone();
let entity = world.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let item = inventory.item_at(item_index).clone();
if item.affixes.iter().any(|affix| {
if let ItemAffix::Socket(None) = affix {
true
} else {
false
}
}) {
let socket_object = scene.resources.get_mut::<Option<ReferenceObject>>();
*socket_object = Some(ReferenceObject::Item {
item,
source: ReferenceItemSource::Inventory(item_index),
});
if item.affixes.iter().any(|affix| {
if let ItemAffix::Socket(None) = affix {
true
} else {
has_empty_sockets = false;
false
}
}) {
let socket_object = world.resources.get_mut::<Option<ReferenceObject>>();
Ok(())
})?;
*socket_object = Some(ReferenceObject::Item {
item,
source: ReferenceItemSource::Inventory(item_index),
});
} else {
has_empty_sockets = false;
}
Ok(has_empty_sockets)
}
fn equip_item(engine: &Arc<Engine>, hero: Entity, item_index: usize) -> Result<()> {
engine.on_scene_mut(|scene| {
let (resources, entity) = scene.entity_resource(hero)?;
fn equip_item(world: &mut World, hero: Entity, item_index: usize) -> Result<()> {
let (entity, resources) = world.entity_resources(hero)?;
let mut multi_mut = entity.multi_mut();
let mut multi_mut = entity.multi_mut();
let hero_items = multi_mut.get::<ItemSlotContainer>()?;
let inventory = multi_mut.get::<Inventory<A>>()?;
let attributes = multi_mut.get::<Attributes>()?;
let hero_items = multi_mut.get::<ItemSlotContainer>()?;
let inventory = multi_mut.get::<Inventory<A>>()?;
let attributes = multi_mut.get::<Attributes>()?;
// remove item from inventory
let item = inventory.remove_item(item_index);
// remove item from inventory
let item = inventory.remove_item(item_index);
// add or swap items with equipment
if let Some(old_item) = hero_items.insert(item.clone(), attributes, &mut multi_mut)? {
inventory.insert_item(old_item, item_index);
}
// add or swap items with equipment
if let Some(old_item) = hero_items.insert(item.clone(), attributes, &mut multi_mut)? {
inventory.insert_item(old_item, item_index);
}
// update hero stats
let statistics = multi_mut.get::<Statistics>()?;
// update hero stats
let statistics = multi_mut.get::<Statistics>()?;
statistics.update(
attributes,
resources.get::<AttributeSettings>(),
(&*hero_items, resources.get::<ItemSettings>()),
);
statistics.update(
attributes,
resources.get::<AttributeSettings>(),
(&*hero_items, resources.get::<ItemSettings>()),
);
Ok(())
})
Ok(())
}
fn show_item_tooltip(
engine: &Arc<Engine>,
world: &mut World,
hero: Entity,
item_index: usize,
reference: &Weak<CharacterWindow>,
(x, y, w, _h): (i32, i32, u32, u32),
) -> Result<()> {
engine.on_scene(|scene| {
let entity = scene.entity(hero)?;
let entity = unsafe { remove_life_time(world.entity(hero)?) };
let inventory = entity.get_component::<Inventory<A>>()?;
let attributes = entity.get_component::<Attributes>()?;
let inventory = entity.get_component::<Inventory<A>>()?;
let attributes = entity.get_component::<Attributes>()?;
let target_x = x + w as i32;
let target_y = y;
let target_x = x + w as i32;
let target_y = y;
let item = inventory.item_at(item_index);
let gui =
item.create_tooltip(engine.gui_handler(), attributes, (target_x, target_y))?;
gui.enable()?;
let item = inventory.item_at(item_index);
let gui = item.create_tooltip(world, attributes, (target_x, target_y))?;
gui.enable(world)?;
let window = reference.upgrade().unwrap();
let items = entity.get_component::<ItemSlotContainer>()?;
let window = reference.upgrade().unwrap();
let items = entity.get_component::<ItemSlotContainer>()?;
match items.item_at(item.slot) {
Some(equipped) => {
let grid_pos = gui.position_extent();
match items.item_at(item.slot) {
Some(equipped) => {
let grid_pos = gui.position_extent();
let spacing = 2;
let start_x = grid_pos.0 + grid_pos.2 as i32 + spacing;
let start_y = grid_pos.1;
let spacing = 2;
let start_x = grid_pos.0 + grid_pos.2 as i32 + spacing;
let start_y = grid_pos.1;
let compare_gui = equipped.create_tooltip(
engine.gui_handler(),
attributes,
(start_x, start_y),
)?;
compare_gui.enable()?;
gui.perform_double_check(&compare_gui, x, spacing as u32)?;
let compare_gui = equipped.create_tooltip(world, attributes, (start_x, start_y))?;
compare_gui.enable(world)?;
gui.perform_double_check(
&compare_gui,
world.resources.get_mut::<GuiHandler>(),
x,
spacing as u32,
)?;
window.add_tooltip("equip", compare_gui);
}
None => {
gui.perform_single_check(x, y)?;
}
window.add_tooltip("equip", compare_gui);
}
None => {
gui.perform_single_check(world.resources.get_mut::<GuiHandler>(), x, y)?;
}
}
window.add_tooltip(format!("item_{item_index}"), gui);
Ok(())
})?;
window.add_tooltip(format!("item_{item_index}"), gui);
Ok(())
}
}
impl<A: Ability + 'static> ContentUpdate for Content<A, Item> {
fn update(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()> {
fn update(&mut self, world: &mut World, hero: Entity) -> Result<()> {
let reference = self.reference.clone();
self.update_base(engine, |button, t, index| {
button.set_icon(&t.icon)?;
self.update_base(world, |world, button, t, index| {
button.set_icon(world.resources.get_mut::<GuiHandler>(), &t.icon)?;
button.set_custom_callback({
let reference = reference.clone();
let engine = engine.clone();
move |controller_button| {
move |world, controller_button| {
Ok(match controller_button {
ControllerButton::X => {
Self::salvage_item(&engine, hero, index)?;
Self::salvage_item(world, hero, index)?;
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.update_page(true)?;
inventory.update_page(world, true)?;
}
true
}
ControllerButton::Y => {
if Self::select_to_socket(&engine, hero, index)? {
if Self::select_to_socket(world, hero, index)? {
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.switch_to_jewels()?;
inventory.switch_to_jewels(world)?;
}
}
@ -201,16 +190,15 @@ impl<A: Ability + 'static> ContentUpdate for Content<A, Item> {
button.set_callback({
let reference = reference.clone();
let engine = engine.clone();
move || {
Self::equip_item(&engine, hero, index)?;
move |world| {
Self::equip_item(world, hero, index)?;
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.update_page(true)?;
inventory.update_page(world, true)?;
}
Ok(())
@ -220,13 +208,12 @@ impl<A: Ability + 'static> ContentUpdate for Content<A, Item> {
button.set_select_callback({
let weak_button = Arc::downgrade(&button);
let reference = reference.clone();
let engine = engine.clone();
move |selected| {
move |world, selected| {
if selected {
let button_pos = weak_button.upgrade().unwrap().position_extent();
Self::show_item_tooltip(&engine, hero, index, &reference, button_pos)?;
Self::show_item_tooltip(world, hero, index, &reference, button_pos)?;
} else {
let window = reference.upgrade().unwrap();
@ -242,123 +229,114 @@ impl<A: Ability + 'static> ContentUpdate for Content<A, Item> {
})
}
fn select(&self) -> Result<()> {
self.select()
fn select(&self, world: &mut World) -> Result<()> {
self.select(world.resources.get_mut::<GuiHandler>())
}
}
impl<A: Ability + 'static> Content<A, Jewel> {
fn show_jewel_tooltip(
engine: &Arc<Engine>,
world: &mut World,
hero: Entity,
item_index: usize,
reference: &Weak<CharacterWindow>,
(x, y, w, _h): (i32, i32, u32, u32),
) -> Result<()> {
engine.on_scene(|scene| {
let entity = scene.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let entity = world.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let target_x = x + w as i32;
let target_y = y;
let target_x = x + w as i32;
let target_y = y;
let jewel = inventory.jewel_at(item_index);
let gui = jewel.create_tooltip(
engine.gui_handler(),
scene.resources.get::<ItemSettings>(),
(target_x, target_y),
)?;
gui.enable()?;
let jewel = inventory.jewel_at(item_index);
let gui = jewel.create_tooltip(
world,
world.resources.get::<ItemSettings>(),
(target_x, target_y),
)?;
gui.enable(world)?;
gui.perform_single_check(x, y)?;
reference
.upgrade()
.unwrap()
.add_tooltip(format!("jewel_{item_index}"), gui);
Ok(())
})?;
gui.perform_single_check(world.resources.get_mut::<GuiHandler>(), x, y)?;
reference
.upgrade()
.unwrap()
.add_tooltip(format!("jewel_{item_index}"), gui);
Ok(())
}
fn select_to_combine(engine: &Arc<Engine>, hero: Entity, jewel_index: usize) -> Result<()> {
engine.on_scene_mut(|scene| {
let entity = scene.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let jewel = inventory.jewel_at(jewel_index).clone();
fn select_to_combine(world: &mut World, hero: Entity, jewel_index: usize) -> Result<()> {
let entity = world.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let jewel = inventory.jewel_at(jewel_index).clone();
// add to reference
let socket_object = scene.resources.get_mut::<Option<ReferenceObject>>();
*socket_object = Some(ReferenceObject::Jewel {
jewel,
index: jewel_index,
});
// add to reference
let socket_object = world.resources.get_mut::<Option<ReferenceObject>>();
*socket_object = Some(ReferenceObject::Jewel {
jewel,
index: jewel_index,
});
// remove from lower if placed there
let lower_jewels = scene.resources.get_mut::<LowerJewels>();
// remove from lower if placed there
let lower_jewels = world.resources.get_mut::<LowerJewels>();
if let Some(position) = lower_jewels.jewels.iter().position(|jewel| match jewel {
Some((_, index)) => *index == jewel_index,
None => false,
}) {
lower_jewels.jewels[position] = None;
}
if let Some(position) = lower_jewels.jewels.iter().position(|jewel| match jewel {
Some((_, index)) => *index == jewel_index,
None => false,
}) {
lower_jewels.jewels[position] = None;
}
Ok(())
})
Ok(())
}
fn select_to_lower(engine: &Arc<Engine>, hero: Entity, jewel_index: usize) -> Result<()> {
engine.on_scene_mut(|scene| {
let entity = scene.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let jewel = inventory.jewel_at(jewel_index).clone();
fn select_to_lower(world: &mut World, hero: Entity, jewel_index: usize) -> Result<()> {
let entity = world.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let jewel = inventory.jewel_at(jewel_index).clone();
// remove from reference if placed there
let socket_object = scene.resources.get_mut::<Option<ReferenceObject>>();
if let Some(ReferenceObject::Jewel { index, .. }) = socket_object {
if *index == jewel_index {
*socket_object = None;
}
// remove from reference if placed there
let socket_object = world.resources.get_mut::<Option<ReferenceObject>>();
if let Some(ReferenceObject::Jewel { index, .. }) = socket_object {
if *index == jewel_index {
*socket_object = None;
}
}
let lower_jewels = scene.resources.get_mut::<LowerJewels>();
let lower_jewels = world.resources.get_mut::<LowerJewels>();
// check if that jewel is already added
if !lower_jewels.jewels.iter().any(|content| match content {
Some((_, index)) => *index == jewel_index,
None => false,
}) {
// search for an empty position in lower jewels
match lower_jewels.jewels.iter().position(|jewel| jewel.is_none()) {
Some(position) => lower_jewels.jewels[position] = Some((jewel, jewel_index)),
None => lower_jewels.jewels[0] = Some((jewel, jewel_index)),
}
// check if that jewel is already added
if !lower_jewels.jewels.iter().any(|content| match content {
Some((_, index)) => *index == jewel_index,
None => false,
}) {
// search for an empty position in lower jewels
match lower_jewels.jewels.iter().position(|jewel| jewel.is_none()) {
Some(position) => lower_jewels.jewels[position] = Some((jewel, jewel_index)),
None => lower_jewels.jewels[0] = Some((jewel, jewel_index)),
}
}
Ok(())
})
Ok(())
}
}
impl<A: Ability + 'static> ContentUpdate for Content<A, Jewel> {
fn update(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()> {
fn update(&mut self, world: &mut World, hero: Entity) -> Result<()> {
let reference = self.reference.clone();
self.update_base(engine, |button, t, index| {
button.set_icon(&t.icon())?;
self.update_base(world, |world, button, t, index| {
button.set_icon(world.resources.get_mut::<GuiHandler>(), &t.icon())?;
button.set_select_callback({
let weak_button = Arc::downgrade(&button);
let engine = engine.clone();
let reference = reference.clone();
move |selected| {
move |world, selected| {
if selected {
let button_pos = weak_button.upgrade().unwrap().position_extent();
Self::show_jewel_tooltip(&engine, hero, index, &reference, button_pos)?;
Self::show_jewel_tooltip(world, hero, index, &reference, button_pos)?;
} else {
let window = reference.upgrade().unwrap();
@ -370,17 +348,16 @@ impl<A: Ability + 'static> ContentUpdate for Content<A, Jewel> {
});
button.set_callback({
let engine = engine.clone();
let reference = reference.clone();
move || {
Self::select_to_lower(&engine, hero, index)?;
move |world| {
Self::select_to_lower(world, hero, index)?;
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.update_page(true)?;
inventory.update_page(world, true)?;
}
Ok(())
@ -388,19 +365,18 @@ impl<A: Ability + 'static> ContentUpdate for Content<A, Jewel> {
});
button.set_custom_callback({
let engine = engine.clone();
let reference = reference.clone();
move |controller_button| {
move |world, controller_button| {
Ok(match controller_button {
ControllerButton::Y => {
Self::select_to_combine(&engine, hero, index)?;
Self::select_to_combine(world, hero, index)?;
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.update_page(true)?;
inventory.update_page(world, true)?;
}
true
@ -415,21 +391,21 @@ impl<A: Ability + 'static> ContentUpdate for Content<A, Jewel> {
})
}
fn select(&self) -> Result<()> {
self.select()
fn select(&self, world: &mut World) -> Result<()> {
self.select(world.resources.get_mut::<GuiHandler>())
}
}
impl<A: Ability + 'static> ContentUpdate for Content<A, MapItem> {
fn update(&mut self, engine: &Arc<Engine>, _hero: Entity) -> Result<()> {
self.update_base(engine, |_button, _t, _index| {
fn update(&mut self, world: &mut World, _hero: Entity) -> Result<()> {
self.update_base(world, |_world, _button, _t, _index| {
// button.set_icon(&t.icon)?;
Ok(())
})
}
fn select(&self) -> Result<()> {
self.select()
fn select(&self, world: &mut World) -> Result<()> {
self.select(world.resources.get_mut::<GuiHandler>())
}
}

View file

@ -1,3 +1,5 @@
use anyhow::Result;
use assetpath::AssetPath;
use rpg_components::{
components::{
attributes::Attributes, character_status::CharacterStatus, inventory::Inventory,
@ -24,83 +26,84 @@ pub struct ItemRightSide {
impl ItemRightSide {
pub fn new<A: Ability + 'static>(
engine: &Arc<Engine>,
world: &mut World,
file: &str,
reference: &Weak<CharacterWindow>,
hero: Entity,
) -> Result<Self> {
let snippet = GuiSnippet::from_str(engine.gui_handler(), file)?;
let icons = InventoryEmptyIcons::new(engine)?;
let snippet = GuiSnippet::from_str(world, file)?;
let icons = InventoryEmptyIcons::new(world)?;
let me = Self {
snippet,
empty_icons: icons,
};
me.setup::<A>(engine, reference, hero)?;
me.setup::<A>(reference, hero)?;
Ok(me)
}
fn setup<A: Ability + 'static>(
&self,
engine: &Arc<Engine>,
reference: &Weak<CharacterWindow>,
hero: Entity,
) -> Result<()> {
button_setup!(self, engine, reference, hero, helmet, "helmet");
button_setup!(self, engine, reference, hero, chest, "chest");
button_setup!(self, engine, reference, hero, gloves, "gloves");
button_setup!(self, engine, reference, hero, belt, "belt");
button_setup!(self, engine, reference, hero, boots, "boots");
button_setup!(self, reference, hero, helmet, "helmet");
button_setup!(self, reference, hero, chest, "chest");
button_setup!(self, reference, hero, gloves, "gloves");
button_setup!(self, reference, hero, belt, "belt");
button_setup!(self, reference, hero, boots, "boots");
#[rustfmt::skip]
button_setup!(self, engine, reference, hero, primary_hand, "main hand");
button_setup!(self, reference, hero, primary_hand, "main hand");
#[rustfmt::skip]
button_setup!(self, engine, reference, hero, secondary_hand, "off hand");
button_setup!(self, reference, hero, secondary_hand, "off hand");
#[rustfmt::skip]
button_setup!(self, engine, reference, hero, amulet, "amulet_0", 0);
button_setup!(self, reference, hero, amulet, "amulet_0", 0);
#[rustfmt::skip]
button_setup!(self, engine, reference, hero, amulet, "amulet_1", 1);
button_setup!(self, reference, hero, amulet, "amulet_1", 1);
#[rustfmt::skip]
button_setup!(self, engine, reference, hero, ring, "ring_0", 0);
button_setup!(self, reference, hero, ring, "ring_0", 0);
#[rustfmt::skip]
button_setup!(self, engine, reference, hero, ring, "ring_1", 1);
button_setup!(self, reference, hero, ring, "ring_1", 1);
#[rustfmt::skip]
button_setup!(self, engine, reference, hero, ring, "ring_2", 2);
button_setup!(self, reference, hero, ring, "ring_2", 2);
#[rustfmt::skip]
button_setup!(self, engine, reference, hero, ring, "ring_3", 3);
button_setup!(self, reference, hero, ring, "ring_3", 3);
Ok(())
}
fn update_icons(&self, items: &ItemSlotContainer) -> Result<()> {
fn update_icons(&self, gui_handler: &mut GuiHandler, items: &ItemSlotContainer) -> Result<()> {
let ui = &self.snippet;
let empty_icons = &self.empty_icons;
equip_update!(ui, items, helmet, empty_icons);
equip_update!(ui, items, chest, empty_icons);
equip_update!(ui, items, boots, empty_icons);
equip_update!(ui, items, gloves, empty_icons);
equip_update!(ui, items, belt, empty_icons);
equip_update!(ui, gui_handler, items, helmet, empty_icons);
equip_update!(ui, gui_handler, items, chest, empty_icons);
equip_update!(ui, gui_handler, items, boots, empty_icons);
equip_update!(ui, gui_handler, items, gloves, empty_icons);
equip_update!(ui, gui_handler, items, belt, empty_icons);
equip_update!(ui, items, primary_hand, empty_icons, "main hand");
equip_update!(ui, items, secondary_hand, empty_icons, "off hand");
#[rustfmt::skip]
equip_update!(ui,gui_handler, items, primary_hand, empty_icons, "main hand");
#[rustfmt::skip]
equip_update!(ui, gui_handler,items, secondary_hand, empty_icons, "off hand");
equip_update!(ui, items, ring, empty_icons, "ring_0", 0);
equip_update!(ui, items, ring, empty_icons, "ring_1", 1);
equip_update!(ui, items, ring, empty_icons, "ring_2", 2);
equip_update!(ui, items, ring, empty_icons, "ring_3", 3);
equip_update!(ui, gui_handler, items, ring, empty_icons, "ring_0", 0);
equip_update!(ui, gui_handler, items, ring, empty_icons, "ring_1", 1);
equip_update!(ui, gui_handler, items, ring, empty_icons, "ring_2", 2);
equip_update!(ui, gui_handler, items, ring, empty_icons, "ring_3", 3);
equip_update!(ui, items, amulet, empty_icons, "amulet_0", 0);
equip_update!(ui, items, amulet, empty_icons, "amulet_1", 1);
equip_update!(ui, gui_handler, items, amulet, empty_icons, "amulet_0", 0);
equip_update!(ui, gui_handler, items, amulet, empty_icons, "amulet_1", 1);
Ok(())
}
fn create_tooltip(
engine: &Arc<Engine>,
world: &mut World,
item: &Item,
attributes: &Attributes,
(x, y, w, _h): (i32, i32, u32, u32),
@ -108,27 +111,20 @@ impl ItemRightSide {
let target_x = x + w as i32;
let target_y = y;
let gui = item.create_tooltip(engine.gui_handler(), attributes, (target_x, target_y))?;
gui.enable()?;
gui.perform_single_check(x, y)?;
let gui = item.create_tooltip(world, attributes, (target_x, target_y))?;
gui.enable(world)?;
gui.perform_single_check(world.resources.get_mut::<GuiHandler>(), x, y)?;
Ok(gui)
}
}
impl RightSide for ItemRightSide {
fn refresh(&mut self, engine: &Engine, hero: Entity) -> Result<()> {
engine.on_scene(|scene| {
let hero_object = scene.entity(hero)?;
fn refresh(&mut self, world: &mut World, hero: Entity) -> Result<()> {
let (hero_object, resources) = world.entity_resources(hero)?;
let items = hero_object.get_component::<ItemSlotContainer>()?;
let items = hero_object.get_component::<ItemSlotContainer>()?;
self.update_icons(items)?;
Ok(())
})?;
Ok(())
self.update_icons(resources.get_mut::<GuiHandler>(), items)
}
fn base(&self) -> &Arc<GuiSnippet> {
@ -151,88 +147,73 @@ struct InventoryEmptyIcons {
}
impl InventoryEmptyIcons {
fn new(engine: &Engine) -> Result<Self> {
let place_holder_settings = &engine
.scene()
fn new(world: &World) -> Result<Self> {
let place_holder_settings = &world
.resources
.get::<ItemSettings>()
.icon_place_holder_paths;
let context = world.resources.get::<Context>();
Ok(Self {
helmet: Image::from_file(place_holder_settings.helmet.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
chest: Image::from_file(place_holder_settings.chest.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
belt: Image::from_file(place_holder_settings.belt.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
boots: Image::from_file(place_holder_settings.boots.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
gloves: Image::from_file(place_holder_settings.gloves.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
helmet: Self::image(context, &place_holder_settings.helmet)?,
chest: Self::image(context, &place_holder_settings.chest)?,
belt: Self::image(context, &place_holder_settings.belt)?,
boots: Self::image(context, &place_holder_settings.boots)?,
gloves: Self::image(context, &place_holder_settings.gloves)?,
primary_hand: Image::from_file(place_holder_settings.main_hand.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
secondary_hand: Image::from_file(place_holder_settings.off_hand.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
primary_hand: Self::image(context, &place_holder_settings.main_hand)?,
secondary_hand: Self::image(context, &place_holder_settings.off_hand)?,
ring: Image::from_file(place_holder_settings.ring.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
amulet: Image::from_file(place_holder_settings.amulet.clone())?
.attach_sampler(Sampler::pretty_sampler().build(engine.device())?)
.build(engine.device(), engine.queue())?,
ring: Self::image(context, &place_holder_settings.ring)?,
amulet: Self::image(context, &place_holder_settings.amulet)?,
})
}
fn image(context: &Context, path: &AssetPath) -> Result<Arc<Image>> {
Image::from_file(path.clone())?
.max_mip_map_levels()
.attach_pretty_sampler(context.device())?
.build(context.device(), context.queue())
}
}
mod macros {
#[macro_export]
macro_rules! button_setup {
($self:ident, $engine:ident, $reference:ident, $hero:ident, $item:ident, $button:literal) => {
($self:ident, $reference:ident, $hero:ident, $item:ident, $button:literal) => {
paste::expr! {
let [<$item _button>]: Arc<Button> = $self.snippet.element($button)?;
[<$item _button>].set_select_callback({
let engine = $engine.clone();
let reference = $reference.clone();
let weak_button = Arc::downgrade(&[<$item _button>]);
move |selected| {
move |world, selected| {
if selected {
engine.on_scene(|scene| {
let entity = scene.entity($hero)?;
let entity = unsafe { remove_life_time(world.entity($hero)?) };
let attributes = entity.get_component::<Attributes>()?;
let items = entity.get_component::<ItemSlotContainer>()?;
let attributes = entity.get_component::<Attributes>()?;
let items = entity.get_component::<ItemSlotContainer>()?;
match items.$item() {
Some($item) => {
let button_pos =
weak_button.upgrade().unwrap().position_extent();
match items.$item() {
Some($item) => {
let button_pos =
weak_button.upgrade().unwrap().position_extent();
let gui = Self::create_tooltip(
&engine,
$item,
attributes,
button_pos,
)?;
let gui = Self::create_tooltip(
world,
$item,
attributes,
button_pos,
)?;
reference.upgrade().unwrap().add_tooltip("equip", gui);
}
None => {
reference.upgrade().unwrap().remove_tooltip("equip");
}
reference.upgrade().unwrap().add_tooltip("equip", gui);
}
Ok(())
})?;
None => {
reference.upgrade().unwrap().remove_tooltip("equip");
}
}
} else {
reference.upgrade().unwrap().remove_tooltip("equip");
}
@ -242,52 +223,45 @@ mod macros {
});
[<$item _button>].set_callback({
let engine = $engine.clone();
let reference = $reference.clone();
move || {
move |world| {
let mut found_item = false;
engine.on_scene_mut(|scene| {
let (resources, entity) = scene.entity_resource($hero)?;
let mut multi_mut = entity.multi_mut();
let (entity, resources) = world.entity_resources($hero)?;
let mut multi_mut = entity.multi_mut();
let items = multi_mut.get::<ItemSlotContainer>()?;
let inventory = multi_mut.get::<Inventory<A>>()?;
let items = multi_mut.get::<ItemSlotContainer>()?;
let inventory = multi_mut.get::<Inventory<A>>()?;
if let Some($item) = items.[<$item>]() {
inventory.add_item($item.clone());
found_item = true;
}
if found_item {
items.[<unset_ $item>](&mut multi_mut)?;
let statistics = multi_mut.get::<Statistics>()?;
let attributes = multi_mut.get::<Attributes>()?;
statistics.update(
attributes,
resources.get::<AttributeSettings>(),
(&*items, resources.get::<ItemSettings>())
);
let status = multi_mut.get::<CharacterStatus>()?;
if status.current_health > statistics.health {
status.current_health = statistics.health.clone();
}
}
Ok(())
})?;
if let Some($item) = items.[<$item>]() {
inventory.add_item($item.clone());
found_item = true;
}
if found_item {
items.[<unset_ $item>](&mut multi_mut)?;
let statistics = multi_mut.get::<Statistics>()?;
let attributes = multi_mut.get::<Attributes>()?;
statistics.update(
attributes,
resources.get::<AttributeSettings>(),
(&*items, resources.get::<ItemSettings>())
);
let status = multi_mut.get::<CharacterStatus>()?;
if status.current_health > statistics.health {
status.current_health = statistics.health.clone();
}
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.update_page(true)?;
inventory.update_page(world, true)?;
}
}
@ -296,46 +270,41 @@ mod macros {
});
[<$item _button>].set_custom_callback({
let engine = $engine.clone();
let reference = $reference.clone();
move |controller_button| {
move |world, controller_button| {
Ok(match controller_button {
ControllerButton::Y => {
let mut empty_affixes_found = false;
engine.on_scene_mut(|scene| {
let entity = scene.entity_mut($hero)?;
let items = entity.get_component::<ItemSlotContainer>()?;
let entity = world.entity_mut($hero)?;
let items = entity.get_component::<ItemSlotContainer>()?;
if let Some(item) = items.$item().clone() {
if item.affixes.iter().any(|affix| {
if let ItemAffix::Socket(None) = affix {
true
} else {
false
}
}) {
let socket_object = scene.resources.get_mut::<Option<ReferenceObject>>();
*socket_object = Some(ReferenceObject::Item {
item,
source: ReferenceItemSource::Slots(None),
});
empty_affixes_found = true;
if let Some(item) = items.$item().clone() {
if item.affixes.iter().any(|affix| {
if let ItemAffix::Socket(None) = affix {
true
} else {
false
}
}
}) {
let socket_object = world.resources.get_mut::<Option<ReferenceObject>>();
Ok(())
})?;
*socket_object = Some(ReferenceObject::Item {
item,
source: ReferenceItemSource::Slots(None),
});
empty_affixes_found = true;
}
}
if empty_affixes_found {
let window = reference.upgrade().unwrap();
let mut tabs = window.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.switch_to_jewels()?;
inventory.switch_to_jewels(world)?;
}
true
@ -347,44 +316,39 @@ mod macros {
});
}
};
($self:ident, $engine:ident, $reference:ident, $hero:ident, $item:ident, $button:literal, $index:literal) => {
($self:ident, $reference:ident, $hero:ident, $item:ident, $button:literal, $index:literal) => {
paste::expr! {
let [<$item _button>]: Arc<Button> = $self.snippet.element($button)?;
[<$item _button>].set_select_callback({
let engine = $engine.clone();
let reference = $reference.clone();
let weak_button = Arc::downgrade(&[<$item _button>]);
move |selected| {
move |world, selected| {
if selected {
engine.on_scene(|scene| {
let entity = scene.entity($hero)?;
let entity = unsafe { remove_life_time(world.entity($hero)?) };
let attributes = entity.get_component::<Attributes>()?;
let items = entity.get_component::<ItemSlotContainer>()?;
let attributes = entity.get_component::<Attributes>()?;
let items = entity.get_component::<ItemSlotContainer>()?;
match items.$item($index) {
Some($item) => {
let button_pos =
weak_button.upgrade().unwrap().position_extent();
match items.$item($index) {
Some($item) => {
let button_pos =
weak_button.upgrade().unwrap().position_extent();
let gui = Self::create_tooltip(
&engine,
$item,
attributes,
button_pos,
)?;
let gui = Self::create_tooltip(
world,
$item,
attributes,
button_pos,
)?;
reference.upgrade().unwrap().add_tooltip("equip", gui);
}
None => {
reference.upgrade().unwrap().remove_tooltip("equip");
}
reference.upgrade().unwrap().add_tooltip("equip", gui);
}
Ok(())
})?;
None => {
reference.upgrade().unwrap().remove_tooltip("equip");
}
}
} else {
reference.upgrade().unwrap().remove_tooltip("equip");
}
@ -394,52 +358,45 @@ mod macros {
});
[<$item _button>].set_callback({
let engine = $engine.clone();
let reference = $reference.clone();
move || {
move |world| {
let mut found_item = false;
engine.on_scene_mut(|scene| {
let (resources, entity) = scene.entity_resource($hero)?;
let mut multi_mut = entity.multi_mut();
let (entity, resources) = world.entity_resources($hero)?;
let mut multi_mut = entity.multi_mut();
let items = multi_mut.get::<ItemSlotContainer>()?;
let inventory = multi_mut.get::<Inventory<A>>()?;
let items = multi_mut.get::<ItemSlotContainer>()?;
let inventory = multi_mut.get::<Inventory<A>>()?;
if let Some($item) = items.[<$item>]($index) {
inventory.add_item($item.clone());
found_item = true;
}
if found_item {
items.[<unset_ $item>]($index)?;
let statistics = multi_mut.get::<Statistics>()?;
let attributes = multi_mut.get::<Attributes>()?;
statistics.update(
attributes,
resources.get::<AttributeSettings>(),
(&*items, resources.get::<ItemSettings>())
);
let status = multi_mut.get::<CharacterStatus>()?;
if status.current_health > statistics.health {
status.current_health = statistics.health.clone();
}
}
Ok(())
})?;
if let Some($item) = items.[<$item>]($index) {
inventory.add_item($item.clone());
found_item = true;
}
if found_item {
items.[<unset_ $item>]($index)?;
let statistics = multi_mut.get::<Statistics>()?;
let attributes = multi_mut.get::<Attributes>()?;
statistics.update(
attributes,
resources.get::<AttributeSettings>(),
(&*items, resources.get::<ItemSettings>())
);
let status = multi_mut.get::<CharacterStatus>()?;
if status.current_health > statistics.health {
status.current_health = statistics.health.clone();
}
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.update_page(true)?;
inventory.update_page(world, true)?;
}
}
@ -448,46 +405,41 @@ mod macros {
});
[<$item _button>].set_custom_callback({
let engine = $engine.clone();
let reference = $reference.clone();
move |controller_button| {
move |world, controller_button| {
Ok(match controller_button {
ControllerButton::Y => {
let mut empty_affixes_found = false;
engine.on_scene_mut(|scene| {
let entity = scene.entity_mut($hero)?;
let items = entity.get_component::<ItemSlotContainer>()?;
let entity = world.entity_mut($hero)?;
let items = entity.get_component::<ItemSlotContainer>()?;
if let Some(item) = items.$item($index).clone() {
if item.affixes.iter().any(|affix| {
if let ItemAffix::Socket(None) = affix {
true
} else {
false
}
}) {
let socket_object = scene.resources.get_mut::<Option<ReferenceObject>>();
*socket_object = Some(ReferenceObject::Item {
item,
source: ReferenceItemSource::Slots(Some($index)),
});
empty_affixes_found = true;
if let Some(item) = items.$item($index).clone() {
if item.affixes.iter().any(|affix| {
if let ItemAffix::Socket(None) = affix {
true
} else {
false
}
}
}) {
let socket_object = world.resources.get_mut::<Option<ReferenceObject>>();
Ok(())
})?;
*socket_object = Some(ReferenceObject::Item {
item,
source: ReferenceItemSource::Slots(Some($index)),
});
empty_affixes_found = true;
}
}
if empty_affixes_found {
let window = reference.upgrade().unwrap();
let mut tabs = window.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.switch_to_jewels()?;
inventory.switch_to_jewels(world)?;
}
true
@ -503,28 +455,28 @@ mod macros {
#[macro_export]
macro_rules! equip_update {
($gui:ident, $items:ident, $part:ident, $icons:ident) => {{
($gui:ident, $gui_handler:ident, $items:ident, $part:ident, $icons:ident) => {{
let button: Arc<Button> = $gui.element(stringify!($part))?;
match $items.$part() {
Some($part) => button.set_icon(&$part.icon)?,
None => button.set_icon(&$icons.$part)?,
Some($part) => button.set_icon($gui_handler, &$part.icon)?,
None => button.set_icon($gui_handler, &$icons.$part)?,
}
}};
($gui:ident, $items:ident, $part:ident, $icons:ident, $name:literal) => {{
($gui:ident, $gui_handler:ident, $items:ident, $part:ident, $icons:ident, $name:literal) => {{
let button: Arc<Button> = $gui.element($name)?;
match $items.$part() {
Some($part) => button.set_icon(&$part.icon)?,
None => button.set_icon(&$icons.$part)?,
Some($part) => button.set_icon($gui_handler, &$part.icon)?,
None => button.set_icon($gui_handler, &$icons.$part)?,
}
}};
($gui:ident, $items:ident, $part:ident, $icons:ident, $name:literal, $index:literal) => {{
($gui:ident, $gui_handler:ident, $items:ident, $part:ident, $icons:ident, $name:literal, $index:literal) => {{
let button: Arc<Button> = $gui.element($name)?;
match $items.$part($index) {
Some($part) => button.set_icon(&$part.icon)?,
None => button.set_icon(&$icons.$part)?,
Some($part) => button.set_icon($gui_handler, &$part.icon)?,
None => button.set_icon($gui_handler, &$icons.$part)?,
}
}};
}

View file

@ -46,8 +46,13 @@ pub struct JewelRightSide {
}
impl JewelRightSide {
pub fn new<A: Ability + 'static>(world: &mut World, file: &str, hero: Entity) -> Result<Self> {
let snippet = GuiSnippet::from_str(world.resources.get_mut::<GuiHandler>(), file)?;
pub fn new<A: Ability + 'static>(
world: &mut World,
file: &str,
hero: Entity,
reference: &Weak<CharacterWindow>,
) -> Result<Self> {
let snippet = GuiSnippet::from_str(world, file)?;
let combine: Arc<Label> = snippet.element("combine")?;
let icon = world.resources.get::<EngineSettings>().controller_icon(
@ -62,25 +67,23 @@ impl JewelRightSide {
world.resources.insert_if_not_exists::<LowerJewels>();
let me = Self { snippet };
me.setup_select::<A>(engine, hero, reference)?;
me.setup_select::<A>(hero, reference)?;
Ok(me)
}
fn setup_select<A: Ability + 'static>(
&self,
engine: &Arc<Engine>,
hero: Entity,
reference: &Weak<CharacterWindow>,
) -> Result<()> {
let (top, bottom) = self.elements()?;
top.set_select_callback({
let engine = engine.clone();
let weak_top = Arc::downgrade(&top);
let reference = reference.clone();
move |selected| {
move |world, selected| {
let menu = reference.upgrade().unwrap();
if selected {
@ -90,25 +93,28 @@ impl JewelRightSide {
let (x, y, w, _h) = button.position_extent();
let scene = engine.scene();
let reference_info = scene.resources.get::<Option<ReferenceObject>>();
let reference_info = world.resources.get::<Option<ReferenceObject>>();
if let Some(reference_info) = reference_info {
let tooltip = match reference_info {
ReferenceObject::Item { item, .. } => item.create_tooltip(
engine.gui_handler(),
scene.entity(hero)?.get_component::<Attributes>()?,
world,
world.entity(hero)?.get_component::<Attributes>()?,
(x + w as i32, y),
)?,
ReferenceObject::Jewel { jewel, .. } => jewel.create_tooltip(
engine.gui_handler(),
scene.resources.get::<ItemSettings>(),
world,
world.resources.get::<ItemSettings>(),
(x + w as i32, y),
)?,
};
tooltip.enable()?;
tooltip.perform_single_check(x, y)?;
tooltip.enable(world)?;
tooltip.perform_single_check(
world.resources.get_mut::<GuiHandler>(),
x,
y,
)?;
menu.add_tooltip("upper", tooltip);
}
@ -122,11 +128,10 @@ impl JewelRightSide {
for (index, lower) in bottom.iter().enumerate() {
lower.set_select_callback({
let engine = engine.clone();
let weak_top = Arc::downgrade(&lower);
let reference = reference.clone();
move |selected| {
move |world, selected| {
let menu = reference.upgrade().unwrap();
if selected {
@ -136,19 +141,21 @@ impl JewelRightSide {
let (x, y, w, _h) = button.position_extent();
let scene = engine.scene();
let lower_info = scene.resources.get::<LowerJewels>();
let lower_info = world.resources.get::<LowerJewels>();
if let Some((lower_jewel, _)) = &lower_info.jewels[index] {
let tooltip = lower_jewel.create_tooltip(
engine.gui_handler(),
scene.resources.get::<ItemSettings>(),
world,
world.resources.get::<ItemSettings>(),
(x + w as i32, y),
)?;
tooltip.enable()?;
tooltip.perform_single_check(x, y)?;
tooltip.enable(world)?;
tooltip.perform_single_check(
world.resources.get_mut::<GuiHandler>(),
x,
y,
)?;
menu.add_tooltip(format!("lower_{index}",), tooltip);
}
@ -161,13 +168,10 @@ impl JewelRightSide {
});
lower.set_callback({
let engine = engine.clone();
let reference = reference.clone();
move || {
let scene = engine.scene_mut();
let lower_info = scene.resources.get_mut::<LowerJewels>();
move |world| {
let lower_info = world.resources.get_mut::<LowerJewels>();
if lower_info.jewels[index].is_some() {
lower_info.jewels[index] = None;
@ -176,7 +180,7 @@ impl JewelRightSide {
let mut tabs = menu.tabs_mut();
let inventory = tabs.inventory::<A>();
inventory.update_page(true)?;
inventory.update_page(world, true)?;
}
}
@ -201,11 +205,9 @@ impl JewelRightSide {
))
}
pub fn clear(engine: &Arc<Engine>) {
let scene = engine.scene_mut();
*scene.resources.get_mut::<Option<ReferenceObject>>() = None;
scene
pub fn clear(world: &mut World) {
*world.resources.get_mut::<Option<ReferenceObject>>() = None;
world
.resources
.get_mut::<LowerJewels>()
.jewels
@ -213,10 +215,8 @@ impl JewelRightSide {
.for_each(|j| *j = None);
}
pub fn combine<A: Ability + 'static>(engine: &Arc<Engine>, hero: Entity) -> Result<bool> {
let scene = engine.scene_mut();
let (resources, entity) = scene.entity_resource(hero)?;
pub fn combine<A: Ability + 'static>(world: &mut World, hero: Entity) -> Result<bool> {
let (entity, resources) = world.entity_resources(hero)?;
let mut resources = resources.multi_mut();
let reference_info = resources.get::<Option<ReferenceObject>>();
@ -359,41 +359,39 @@ impl JewelRightSide {
}
impl RightSide for JewelRightSide {
fn refresh(&mut self, engine: &Engine, _hero: Entity) -> Result<()> {
engine.on_scene(|scene| {
let (reference, lower) = self.elements()?;
fn refresh(&mut self, world: &mut World, _hero: Entity) -> Result<()> {
let (reference, lower) = self.elements()?;
let reference_info = scene.resources.get::<Option<ReferenceObject>>();
let lower_info = scene.resources.get::<LowerJewels>();
let mut resources = world.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>();
let reference_info = resources.get::<Option<ReferenceObject>>();
let lower_info = resources.get::<LowerJewels>();
match reference_info.as_ref() {
Some(reference_info) => {
let icon = match reference_info {
ReferenceObject::Item { item, .. } => item.icon(),
ReferenceObject::Jewel { jewel, .. } => jewel.icon(),
};
match reference_info.as_ref() {
Some(reference_info) => {
let icon = match reference_info {
ReferenceObject::Item { item, .. } => item.icon(),
ReferenceObject::Jewel { jewel, .. } => jewel.icon(),
};
reference.set_icon(&icon)?;
}
None => reference.clear_icon()?,
reference.set_icon(gui_handler, &icon)?;
}
None => reference.clear_icon(gui_handler)?,
}
for (jewel, icon) in lower_info.jewels.iter().zip(lower.iter()) {
match jewel.as_ref() {
Some((jewel, _)) => icon.set_icon(&jewel.icon())?,
None => icon.clear_icon()?,
}
for (jewel, icon) in lower_info.jewels.iter().zip(lower.iter()) {
match jewel.as_ref() {
Some((jewel, _)) => icon.set_icon(gui_handler, &jewel.icon())?,
None => icon.clear_icon(gui_handler)?,
}
}
Ok(())
})
Ok(())
}
fn disable(&mut self, engine: &Engine, _hero: Entity) -> Result<()> {
let scene = engine.scene_mut();
*scene.resources.get_mut::<Option<ReferenceObject>>() = None;
scene
fn disable(&mut self, world: &mut World, _hero: Entity) -> Result<()> {
*world.resources.get_mut::<Option<ReferenceObject>>() = None;
world
.resources
.get_mut::<LowerJewels>()
.jewels

View file

@ -9,15 +9,15 @@ pub struct MapRightSide {
}
impl MapRightSide {
pub fn new(engine: &Arc<Engine>, file: &str) -> Result<Self> {
let snippet = GuiSnippet::from_str(engine.gui_handler(), file)?;
pub fn new(world: &mut World, file: &str) -> Result<Self> {
let snippet = GuiSnippet::from_str(world, file)?;
Ok(Self { snippet })
}
}
impl RightSide for MapRightSide {
fn refresh(&mut self, _engine: &Engine, _hero: Entity) -> Result<()> {
fn refresh(&mut self, _world: &mut World, _hero: Entity) -> Result<()> {
Ok(())
}

View file

@ -21,7 +21,6 @@ use map_right_side::MapRightSide;
pub struct InventoryPage<A: Ability + 'static> {
close: Weak<Button>,
engine: Arc<Engine>,
hero: Entity,
grid: Arc<Grid>,
@ -47,11 +46,11 @@ impl<A: Ability + 'static> InventoryPage<A> {
let grid = Grid::new(gui_handler, 2, 1, false)?;
let left_base = GuiSnippet::from_str(
engine.gui_handler(),
world,
include_str!("../../resources/inventory/left_side.xml"),
)?;
grid.attach(left_base.clone(), 0, 0, 1, 1)?;
grid.attach(world, left_base.clone(), 0, 0, 1, 1)?;
Self::setup_content_switch(&left_base, reference.clone())?;
let tooltip = left_base.element("tooltip")?;
@ -59,47 +58,57 @@ impl<A: Ability + 'static> InventoryPage<A> {
// items
let item_mode = PageContent::<A, _>::new(
Content::new::<_, Self>(engine, reference.clone(), {
let engine = engine.clone();
Content::new::<_, Self>(world, reference.clone(), {
let hero = hero.clone();
move || {
let mut data = Vec::new();
move |world: &mut World| {
let hero_object = world.entity(hero)?;
let inventory = hero_object.get_component::<Inventory<A>>()?;
engine.on_scene(|scene| {
let hero_object = scene.entity(hero)?;
let inventory = hero_object.get_component::<Inventory<A>>()?;
data = inventory.iter_items().cloned().collect();
Ok(())
})?;
let data = inventory.iter_items().cloned().collect();
Ok(data)
}
})?,
{
let ui = GuiSnippet::from_str(
engine.gui_handler(),
world,
include_str!("../../resources/inventory/items/tooltip.xml"),
)?;
let mut resources = world.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>();
let engine_settings = resources.get::<EngineSettings>();
let context = resources.get::<Context>();
let equip: Arc<Label> = ui.element("equip")?;
equip.set_info_icon(&engine.controller_icon(ControllerButton::A)?)?;
equip.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::A)?,
)?;
let salvage: Arc<Label> = ui.element("salvage")?;
salvage.set_info_icon(&engine.controller_icon(ControllerButton::X)?)?;
salvage.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::X)?,
)?;
let socket: Arc<Label> = ui.element("socket")?;
socket.set_info_icon(&engine.controller_icon(ControllerButton::Y)?)?;
socket.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::Y)?,
)?;
let switch_mode: Arc<Label> = ui.element("switch_mode")?;
switch_mode.set_info_icon(&engine.controller_icon(ControllerButton::LeftStick)?)?;
switch_mode.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::LeftStick)?,
)?;
ui
},
ItemRightSide::new::<A>(
engine,
world,
include_str!("../../resources/inventory/items/right_side.xml"),
&reference,
hero,
@ -108,44 +117,51 @@ impl<A: Ability + 'static> InventoryPage<A> {
// jewels
let jewel_mode = PageContent::<A, _>::new(
Content::new::<_, Self>(engine, reference.clone(), {
let engine = engine.clone();
Content::new::<_, Self>(world, reference.clone(), {
let hero = hero.clone();
move || {
let mut data = Vec::new();
move |world| {
let hero_object = world.entity(hero)?;
let inventory = hero_object.get_component::<Inventory<A>>()?;
engine.on_scene(|scene| {
let hero_object = scene.entity(hero)?;
let inventory = hero_object.get_component::<Inventory<A>>()?;
data = inventory.iter_jewels().cloned().collect();
Ok(())
})?;
let data = inventory.iter_jewels().cloned().collect();
Ok(data)
}
})?,
{
let ui = GuiSnippet::from_str(
engine.gui_handler(),
world,
include_str!("../../resources/inventory/jewels/tooltip.xml"),
)?;
let mut resources = world.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>();
let engine_settings = resources.get::<EngineSettings>();
let context = resources.get::<Context>();
let socket: Arc<Label> = ui.element("socket")?;
socket.set_info_icon(&engine.controller_icon(ControllerButton::A)?)?;
socket.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::A)?,
)?;
let combine: Arc<Label> = ui.element("combine")?;
combine.set_info_icon(&engine.controller_icon(ControllerButton::Y)?)?;
combine.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::Y)?,
)?;
let switch_mode: Arc<Label> = ui.element("switch_mode")?;
switch_mode.set_info_icon(&engine.controller_icon(ControllerButton::LeftStick)?)?;
switch_mode.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::LeftStick)?,
)?;
ui
},
JewelRightSide::new::<A>(
engine,
world,
include_str!("../../resources/inventory/jewels/right_side.xml"),
hero,
&reference,
@ -154,44 +170,49 @@ impl<A: Ability + 'static> InventoryPage<A> {
// maps
let map_mode = PageContent::<A, _>::new(
Content::new::<_, Self>(engine, reference.clone(), {
let engine = engine.clone();
let hero: Entity = hero.clone();
Content::new::<_, Self>(world, reference.clone(), {
move |world| {
let hero_object = world.entity(hero)?;
let inventory = hero_object.get_component::<Inventory<A>>()?;
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_maps().cloned().collect();
Ok(())
})?;
let data = inventory.iter_maps().cloned().collect();
Ok(data)
}
})?,
{
let ui = GuiSnippet::from_str(
engine.gui_handler(),
world,
include_str!("../../resources/inventory/maps/tooltip.xml"),
)?;
let mut resources = world.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>();
let engine_settings = resources.get::<EngineSettings>();
let context = resources.get::<Context>();
let select: Arc<Label> = ui.element("select")?;
select.set_info_icon(&engine.controller_icon(ControllerButton::A)?)?;
select.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::A)?,
)?;
let start: Arc<Label> = ui.element("start")?;
start.set_info_icon(&engine.controller_icon(ControllerButton::X)?)?;
start.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::X)?,
)?;
let switch_mode: Arc<Label> = ui.element("switch_mode")?;
switch_mode.set_info_icon(&engine.controller_icon(ControllerButton::LeftStick)?)?;
switch_mode.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::LeftStick)?,
)?;
ui
},
MapRightSide::new(
engine,
world,
include_str!("../../resources/inventory/maps/right_side.xml"),
)?,
);
@ -199,7 +220,6 @@ impl<A: Ability + 'static> InventoryPage<A> {
Ok(Self {
close: Arc::downgrade(close),
engine: engine.clone(),
hero,
grid,
@ -219,12 +239,12 @@ impl<A: Ability + 'static> InventoryPage<A> {
})
}
fn switch_to_jewels(&mut self) -> Result<()> {
fn switch_to_jewels(&mut self, world: &mut World) -> Result<()> {
self.current_mode = 1;
self.update_page(true)
self.update_page(world, true)
}
fn update_page(&mut self, select: bool) -> Result<()> {
fn update_page(&mut self, world: &mut World, select: bool) -> Result<()> {
match self.current_mode {
0 => println!("update item view"),
1 => println!("update jewel view"),
@ -236,21 +256,22 @@ impl<A: Ability + 'static> InventoryPage<A> {
{
let mode = &mut self.modes[self.current_mode];
self.tooltip.attach(mode.tooltip().clone(), 0, 0, 1, 1)?;
self.tooltip
.attach(world, mode.tooltip().clone(), 0, 0, 1, 1)?;
self.content
.attach(mode.content_mut().base().clone(), 0, 0, 1, 1)?;
.attach(world, mode.content_mut().base().clone(), 0, 0, 1, 1)?;
self.grid
.attach(mode.right_side_mut().base().clone(), 1, 0, 1, 1)?;
.attach(world, mode.right_side_mut().base().clone(), 1, 0, 1, 1)?;
mode.content_mut().update(&self.engine, self.hero)?;
mode.right_side_mut().refresh(&self.engine, self.hero)?;
mode.content_mut().update(world, self.hero)?;
mode.right_side_mut().refresh(world, self.hero)?;
if select {
mode.content_mut().select()?;
mode.content_mut().select(world)?;
if mode.content_mut().is_empty() {
if let Some(close) = self.close.upgrade() {
close.select()?;
close.select(world.resources.get_mut::<GuiHandler>())?;
}
}
}
@ -319,14 +340,14 @@ impl<A: Ability + 'static> InventoryPage<A> {
let switch = {
let reference = reference.clone();
move |index| {
move |world: &mut World, index| {
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let me = tabs.inventory::<A>();
if me.current_mode != index {
me.current_mode = index;
me.update_page(true)?;
me.update_page(world, true)?;
}
}
@ -337,19 +358,19 @@ impl<A: Ability + 'static> InventoryPage<A> {
let switch_to_items = Box::new({
let switch = switch.clone();
move || switch(0)
move |world: &mut World| switch(world, 0)
});
let switch_to_jewels = Box::new({
let switch = switch.clone();
move || switch(1)
move |world: &mut World| switch(world, 1)
});
let switch_to_maps = Box::new({
let switch = switch.clone();
move || switch(2)
move |world: &mut World| switch(world, 2)
});
left_base.set_click_callbacks(vec![
@ -361,78 +382,78 @@ impl<A: Ability + 'static> InventoryPage<A> {
}
impl<A: Ability + 'static> Page for InventoryPage<A> {
fn enable(&mut self) -> Result<Arc<Grid>> {
fn enable(&mut self, world: &mut World) -> Result<Arc<Grid>> {
println!("enable InventoryPage");
for mode in self.modes.iter_mut() {
mode.content_mut().refresh()?;
mode.content_mut().refresh(world)?;
}
self.update_page(false)?;
self.update_page(world, false)?;
Ok(self.grid.clone())
}
fn disable(&mut self) -> Result<()> {
fn disable(&mut self, world: &mut World) -> Result<()> {
self.modes[self.current_mode]
.right_side_mut()
.disable(&self.engine, self.hero)
.disable(world, self.hero)
}
fn select(&self) -> Result<()> {
fn select(&self, world: &mut World) -> Result<()> {
let mode = &self.modes[self.current_mode];
mode.content().select()?;
mode.content().select(world)?;
if mode.content().is_empty() {
if let Some(close) = self.close.upgrade() {
close.select()?;
close.select(world.resources.get_mut::<GuiHandler>())?;
}
}
Ok(())
}
fn next_tab(&mut self) -> Result<()> {
fn next_tab(&mut self, world: &mut World) -> Result<()> {
{
let mode = &mut self.modes[self.current_mode];
mode.content_mut().next_tab(&self.engine, self.hero)?;
mode.content_mut().select()?;
mode.content_mut().next_tab(world, self.hero)?;
mode.content_mut().select(world)?;
}
self.connect_character_page()
}
fn previous_tab(&mut self) -> Result<()> {
fn previous_tab(&mut self, world: &mut World) -> Result<()> {
{
let mode = &mut self.modes[self.current_mode];
mode.content_mut().previous_tab(&self.engine, self.hero)?;
mode.content_mut().select()?;
mode.content_mut().previous_tab(world, self.hero)?;
mode.content_mut().select(world)?;
}
self.connect_character_page()
}
fn event(&mut self, button: ControllerButton) -> Result<bool> {
fn event(&mut self, world: &mut World, button: ControllerButton) -> Result<bool> {
Ok(match button {
ControllerButton::LeftStick => {
self.modes[self.current_mode]
.right_side_mut()
.disable(&self.engine, self.hero)?;
.disable(world, self.hero)?;
self.current_mode = (self.current_mode + 1) % self.modes.len();
self.update_page(true)?;
self.update_page(world, true)?;
true
}
ControllerButton::RightStick => {
// check if jewel page is open
if self.current_mode == 1 {
if JewelRightSide::combine::<A>(&self.engine, self.hero)? {
JewelRightSide::clear(&self.engine);
self.update_page(true)?;
if JewelRightSide::combine::<A>(world, self.hero)? {
JewelRightSide::clear(world);
self.update_page(world, true)?;
}
true

View file

@ -29,12 +29,12 @@ use std::{
use self::{abilities::AbilityPage, character::CharacterPage, inventory::InventoryPage};
trait Page: Any + Send + Sync + Downcast {
fn enable(&mut self) -> Result<Arc<Grid>>;
fn disable(&mut self) -> Result<()>;
fn select(&self) -> Result<()>;
fn next_tab(&mut self) -> Result<()>;
fn previous_tab(&mut self) -> Result<()>;
fn event(&mut self, button: ControllerButton) -> Result<bool>;
fn enable(&mut self, world: &mut World) -> Result<Arc<Grid>>;
fn disable(&mut self, world: &mut World) -> Result<()>;
fn select(&self, world: &mut World) -> Result<()>;
fn next_tab(&mut self, world: &mut World) -> Result<()>;
fn previous_tab(&mut self, world: &mut World) -> Result<()>;
fn event(&mut self, world: &mut World, button: ControllerButton) -> Result<bool>;
}
impl_downcast!(Page);
@ -134,10 +134,7 @@ impl CharacterWindow {
name: &str,
close: Box<dyn FutureStateChange>,
) -> Result<Arc<Self>> {
let menu_gui = GuiBuilder::from_str(
world.resources.get_mut::<GuiHandler>(),
include_str!("../resources/menu.xml"),
)?;
let menu_gui = GuiBuilder::from_str(world, include_str!("../resources/menu.xml"))?;
let content_grid = menu_gui.element("tab_content")?;
let open_character_page: Arc<Button> = menu_gui.element("open_statistics")?;
@ -164,13 +161,13 @@ impl CharacterWindow {
let open_tab = {
let weak_me = Arc::downgrade(&character_window);
move |gui_handler: &mut GuiHandler, index| {
move |world: &mut World, index| {
if let Some(me) = weak_me.upgrade() {
me.tab.store(index, SeqCst);
me.tab_content_grid
.attach(gui_handler, me.tab_mut().enable()?, 0, 0, 1, 1)?;
me.tab().select()?;
.attach(world, me.tab_mut().enable(world)?, 0, 0, 1, 1)?;
me.tab().select(world)?;
}
Ok(())
@ -180,19 +177,19 @@ impl CharacterWindow {
open_character_page.set_callback({
let open_tab = open_tab.clone();
move |world| open_tab(world.resources.get_mut::<GuiHandler>(), 0)
move |world| open_tab(world, 0)
});
open_inventory_page.set_callback({
let open_tab = open_tab.clone();
move |world| open_tab(world.resources.get_mut::<GuiHandler>(), 1)
move |world| open_tab(world, 1)
});
open_ability_page.set_callback({
let open_tab = open_tab.clone();
move |world| open_tab(world.resources.get_mut::<GuiHandler>(), 2)
move |world| open_tab(world, 2)
});
Self::setup_menu(&character_window)?;
@ -200,8 +197,8 @@ impl CharacterWindow {
Ok(character_window)
}
pub fn event(&self, button: ControllerButton) -> Result<bool> {
self.tabs.write().unwrap()[self.tab.load(SeqCst)].event(button)
pub fn event(&self, world: &mut World, button: ControllerButton) -> Result<bool> {
self.tabs.write().unwrap()[self.tab.load(SeqCst)].event(world, button)
}
pub fn tabs<'a>(&'a self) -> Tabs<'a> {
@ -279,36 +276,41 @@ impl TopLevelGui for CharacterWindow {
None
}
fn enable(&self, gui_handler: &mut GuiHandler) -> Result<()> {
self.menu_gui.enable(gui_handler)?;
fn enable(&self, world: &mut World) -> Result<()> {
self.menu_gui.enable(world)?;
self.tab_content_grid
.attach(gui_handler, self.tab_mut().enable()?, 0, 0, 1, 1)?;
self.tab().select()?;
.attach(world, self.tab_mut().enable(world)?, 0, 0, 1, 1)?;
self.tab().select(world)?;
let mut resources = world.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>();
let engine_settings = resources.get::<EngineSettings>();
let context = resources.get::<Context>();
let close_button: Arc<Button> = self.menu_gui.element("close")?;
close_button.set_info_icon(
gui_handler,
&self.engine.controller_icon(ControllerButton::B)?,
&engine_settings.controller_icon(context, ControllerButton::B)?,
)?;
let left_info: Arc<Icon> = self.menu_gui.element("left_info")?;
left_info.set_icon(
gui_handler,
&self.engine.controller_icon(ControllerButton::LeftButton)?,
&engine_settings.controller_icon(context, ControllerButton::LeftButton)?,
)?;
let right_info: Arc<Icon> = self.menu_gui.element("right_info")?;
right_info.set_icon(
gui_handler,
&self.engine.controller_icon(ControllerButton::RightButton)?,
&engine_settings.controller_icon(context, ControllerButton::RightButton)?,
)?;
Ok(())
}
fn disable(&self, gui_handler: &mut GuiHandler) -> Result<()> {
self.menu_gui.disable(gui_handler)?;
fn disable(&self, world: &mut World) -> Result<()> {
self.menu_gui.disable(world)?;
Ok(())
}
@ -337,24 +339,18 @@ impl TopGui for CharacterWindow {
match second_level {
false => {
// disable old tab
self.tab_mut().disable()?;
self.tab_mut().disable(world)?;
// add to tab index
self.tab.store((self.tab.load(SeqCst) + 1) % 3, SeqCst);
// update tab content
self.tab_content_grid.attach(
world.resources.get_mut::<GuiHandler>(),
self.tab_mut().enable()?,
0,
0,
1,
1,
)?;
self.tab().select()?;
self.tab_content_grid
.attach(world, self.tab_mut().enable(world)?, 0, 0, 1, 1)?;
self.tab().select(world)?;
}
true => {
self.tab_mut().next_tab()?;
self.tab_mut().next_tab(world)?;
}
}
@ -365,7 +361,7 @@ impl TopGui for CharacterWindow {
match second_level {
false => {
// disable old tab
self.tab_mut().disable()?;
self.tab_mut().disable(world)?;
// subtract from tab index
if self.tab.load(SeqCst) == 0 {
@ -375,18 +371,12 @@ impl TopGui for CharacterWindow {
}
// update tab content
self.tab_content_grid.attach(
world.resources.get_mut::<GuiHandler>(),
self.tab_mut().enable()?,
0,
0,
1,
1,
)?;
self.tab().select()?;
self.tab_content_grid
.attach(world, self.tab_mut().enable(world)?, 0, 0, 1, 1)?;
self.tab().select(world)?;
}
true => {
self.tab_mut().previous_tab()?;
self.tab_mut().previous_tab(world)?;
}
}
@ -407,7 +397,7 @@ impl CharacterWindow {
// .add("open_statistics", open_statistics)
// .add("open_abilities", open_abilities)
// .add("open_inventory", open_inventory)
.add("close", |world, _gui_handler| close(world))
.add("close", move |world| close(world))
.into(),
)?;

View file

@ -8,7 +8,7 @@ use super::traits::*;
pub struct EmptyRightSide;
impl RightSide for EmptyRightSide {
fn refresh(&mut self, _engine: &Engine, _hero: Entity) -> Result<()> {
fn refresh(&mut self, _world: &mut World, _hero: Entity) -> Result<()> {
unreachable!()
}

View file

@ -14,9 +14,9 @@ pub trait PageContentWrapper: Send + Sync {
}
pub trait RightSide: Send + Sync {
fn refresh(&mut self, engine: &Engine, hero: Entity) -> Result<()>;
fn refresh(&mut self, world: &mut World, hero: Entity) -> Result<()>;
fn disable(&mut self, _engine: &Engine, _hero: Entity) -> Result<()> {
fn disable(&mut self, _world: &mut World, _hero: Entity) -> Result<()> {
Ok(())
}

View file

@ -245,15 +245,10 @@ impl AbilityAddon {
Ok(item_system.addon(rarity, addon_type))
}
pub fn create_tooltip(
&self,
gui_handler: &mut GuiHandler,
position: (i32, i32),
) -> Result<Tooltip> {
let gui = GuiBuilder::from_str(
gui_handler,
include_str!("../../resources/addon_snippet.xml"),
)?;
pub fn create_tooltip(&self, world: &mut World, position: (i32, i32)) -> Result<Tooltip> {
let gui = GuiBuilder::from_str(world, include_str!("../../resources/addon_snippet.xml"))?;
let gui_handler = world.resources.get_mut::<GuiHandler>();
let icon: Arc<Icon> = gui.element("addon_icon")?;
let rarity_label: Arc<Label> = gui.element("rarity_label")?;

View file

@ -298,14 +298,13 @@ impl<A: Ability> AbilityBook<A> {
pub fn create_tooltip(
&self,
gui_handler: &mut GuiHandler,
world: &mut World,
statistics: &Statistics,
position: (i32, i32),
) -> Result<Tooltip> {
let gui = GuiBuilder::from_str(
gui_handler,
include_str!("../../resources/book_snippet.xml"),
)?;
let gui = GuiBuilder::from_str(world, include_str!("../../resources/book_snippet.xml"))?;
let gui_handler = world.resources.get_mut::<GuiHandler>();
let ability_name: Arc<Label> = gui.element("ability_name")?;
let rarity_label: Arc<Label> = gui.element("rarity_label")?;

View file

@ -233,14 +233,16 @@ impl Item {
pub fn create_tooltip(
&self,
gui_handler: &mut GuiHandler,
world: &mut World,
attributes: &Attributes,
position: (i32, i32),
) -> Result<Tooltip> {
let (stats, jewels) = ItemAffix::squash(self.affixes.iter());
let count = stats.len() + jewels.len();
let inspector_snippet = GuiBuilder::from_str(gui_handler, &ITEM_SNIPPETS[count])?;
let inspector_snippet = GuiBuilder::from_str(world, &ITEM_SNIPPETS[count])?;
let gui_handler = world.resources.get_mut_unchecked::<GuiHandler>();
let item_icon: Arc<Icon> = inspector_snippet.element("item_icon")?;
let slot_label: Arc<Label> = inspector_snippet.element("slot_label")?;
@ -287,10 +289,8 @@ impl Item {
let mut index = Self::INSPECTOR_OFFSET;
for stat in stats {
let stat_type_snippet = GuiSnippet::from_str(
gui_handler,
include_str!("../../resources/stat_type_snippet.xml"),
)?;
let stat_type_snippet =
GuiSnippet::from_str(world, include_str!("../../resources/stat_type_snippet.xml"))?;
let stat_type_label: Arc<Label> = stat_type_snippet.element("stat_type")?;
let stat_value_label: Arc<Label> = stat_type_snippet.element("stat_value")?;
@ -298,14 +298,14 @@ impl Item {
stat_type_label.set_text(gui_handler, &format!("{}", stat))?;
stat_value_label.set_text(gui_handler, &stat.display_value())?;
inspector_grid.attach(gui_handler, stat_type_snippet, 0, index, 1, 1)?;
inspector_grid.attach(world, stat_type_snippet, 0, index, 1, 1)?;
index += 1;
}
for jewel in jewels {
let socket_snippet = GuiSnippet::from_str(
gui_handler,
world,
include_str!("../../resources/item_socket_snippet.xml"),
)?;
@ -329,7 +329,7 @@ impl Item {
}
}
inspector_grid.attach(gui_handler, socket_snippet, 0, index, 1, 1)?;
inspector_grid.attach(world, socket_snippet, 0, index, 1, 1)?;
index += 1;
}

View file

@ -60,14 +60,14 @@ impl Jewel {
pub fn create_tooltip(
&self,
gui_handler: &mut GuiHandler,
world: &mut World,
item_settings: &ItemSettings,
position: (i32, i32),
) -> Result<Tooltip> {
let inspector_snippet: Arc<GuiBuilder> = GuiBuilder::from_str(
gui_handler,
include_str!("../../resources/jewel_tooltip.xml"),
)?;
let inspector_snippet: Arc<GuiBuilder> =
GuiBuilder::from_str(world, include_str!("../../resources/jewel_tooltip.xml"))?;
let gui_handler = world.resources.get_mut::<GuiHandler>();
let main_grid: Arc<Grid> = inspector_snippet.element("main_grid")?;
main_grid.change_position_unscaled(gui_handler, position.0, position.1)?;

View file

@ -18,8 +18,8 @@ impl Tooltip {
Self { grid, gui }
}
pub fn enable(&self, gui_handler: &mut GuiHandler) -> Result<()> {
self.gui.enable(gui_handler)
pub fn enable(&self, world: &mut World) -> Result<()> {
self.gui.enable(world)
}
pub fn check_fitting(