veloren_voxygen/hud/
hotbar.rs

1use common::comp::{
2    self,
3    inventory::item::{Item, item_key::ItemKey},
4};
5use serde::{Deserialize, Serialize};
6
7use super::HudInfo;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum Slot {
11    One = 0,
12    Two = 1,
13    Three = 2,
14    Four = 3,
15    Five = 4,
16    Six = 5,
17    Seven = 6,
18    Eight = 7,
19    Nine = 8,
20    Ten = 9,
21}
22
23#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
24pub enum SlotContents {
25    Inventory(u64, ItemKey),
26    Ability(usize),
27}
28
29#[derive(Clone, Default)]
30pub struct State {
31    pub slots: [Option<SlotContents>; 10],
32    inputs: [bool; 10],
33}
34
35impl State {
36    pub fn new(slots: [Option<SlotContents>; 10]) -> Self {
37        Self {
38            slots,
39            inputs: [false; 10],
40        }
41    }
42
43    /// Returns true if the button was just pressed
44    pub fn process_input(&mut self, slot: Slot, state: bool) -> bool {
45        let slot = slot as usize;
46        let just_pressed = !self.inputs[slot] && state;
47        self.inputs[slot] = state;
48        just_pressed
49    }
50
51    pub fn get(&self, slot: Slot) -> Option<SlotContents> { self.slots[slot as usize].clone() }
52
53    pub fn swap(&mut self, a: Slot, b: Slot) { self.slots.swap(a as usize, b as usize); }
54
55    pub fn clear_slot(&mut self, slot: Slot) { self.slots[slot as usize] = None; }
56
57    pub fn add_inventory_link(&mut self, slot: Slot, item: &Item) {
58        self.slots[slot as usize] = Some(SlotContents::Inventory(
59            item.item_hash(),
60            ItemKey::from(item),
61        ));
62    }
63
64    // TODO: remove pending UI
65    // Adds ability slots if missing and should be present
66    // Removes ability slots if not there and shouldn't be present
67    pub fn maintain_abilities(&mut self, client: &client::Client, info: &HudInfo) {
68        use specs::WorldExt;
69        if let Some(active_abilities) = client
70            .state()
71            .ecs()
72            .read_storage::<comp::ActiveAbilities>()
73            .get(info.viewpoint_entity)
74        {
75            use common::comp::ability::AuxiliaryAbility;
76            for ((i, ability), hotbar_slot) in active_abilities
77                .auxiliary_set(
78                    client.inventories().get(info.viewpoint_entity),
79                    client
80                        .state()
81                        .read_storage::<comp::SkillSet>()
82                        .get(info.viewpoint_entity),
83                )
84                .iter()
85                .enumerate()
86                .zip(self.slots.iter_mut())
87            {
88                if matches!(ability, AuxiliaryAbility::Empty) {
89                    if matches!(hotbar_slot, Some(SlotContents::Ability(_))) {
90                        // If ability is empty but hotbar shows an ability, clear it
91                        *hotbar_slot = None;
92                    }
93                } else {
94                    // If an ability is not empty show it on the hotbar
95                    *hotbar_slot = Some(SlotContents::Ability(i));
96                }
97            }
98        } else {
99            self.slots
100                .iter_mut()
101                .filter(|slot| matches!(slot, Some(SlotContents::Ability(_))))
102                .for_each(|slot| *slot = None)
103        }
104    }
105}