mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Basic hotbar functionality
This commit is contained in:
parent
77d13376d3
commit
f81f91162d
97
voxygen/src/hud/hotbar.rs
Normal file
97
voxygen/src/hud/hotbar.rs
Normal file
@ -0,0 +1,97 @@
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum Slot {
|
||||
One = 0,
|
||||
Two = 1,
|
||||
Three = 2,
|
||||
Four = 3,
|
||||
Five = 4,
|
||||
Six = 5,
|
||||
Seven = 6,
|
||||
Eight = 7,
|
||||
Nine = 8,
|
||||
Ten = 9,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum SlotContents {
|
||||
Inventory(usize),
|
||||
Ability3,
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
slots: [Option<SlotContents>; 10],
|
||||
inputs: [bool; 10],
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
slots: [None; 10],
|
||||
inputs: [false; 10],
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true is the button was just pressed
|
||||
pub fn process_input(&mut self, slot: Slot, state: bool) -> bool {
|
||||
let slot = slot as usize;
|
||||
let just_pressed = !self.inputs[slot] && state;
|
||||
self.inputs[slot] = state;
|
||||
just_pressed
|
||||
}
|
||||
|
||||
pub fn get(&self, slot: Slot) -> Option<SlotContents> { self.slots[slot as usize] }
|
||||
|
||||
pub fn swap(&mut self, a: Slot, b: Slot) { self.slots.swap(a as usize, b as usize); }
|
||||
|
||||
pub fn clear_slot(&mut self, slot: Slot) { self.slots[slot as usize] = None; }
|
||||
|
||||
pub fn add_inventory_link(&mut self, slot: Slot, inventory_index: usize) {
|
||||
self.slots[slot as usize] = Some(SlotContents::Inventory(inventory_index));
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
// Adds ability3 slot if it is missing and should be present
|
||||
// Removes if it is there and shouldn't be present
|
||||
pub fn maintain_ability3(&mut self, client: &client::Client) {
|
||||
use specs::WorldExt;
|
||||
let loadouts = client.state().ecs().read_storage::<common::comp::Loadout>();
|
||||
let loadout = loadouts.get(client.entity());
|
||||
let should_be_present = if let Some(loadout) = loadout {
|
||||
loadout
|
||||
.active_item
|
||||
.as_ref()
|
||||
.map(|i| &i.item.kind)
|
||||
.filter(|kind| {
|
||||
use common::comp::item::{
|
||||
tool::{StaffKind, Tool, ToolKind},
|
||||
ItemKind,
|
||||
};
|
||||
matches!(
|
||||
kind,
|
||||
ItemKind::Tool(Tool {
|
||||
kind: ToolKind::Staff(StaffKind::BasicStaff),
|
||||
..
|
||||
})
|
||||
)
|
||||
})
|
||||
.is_some()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if should_be_present {
|
||||
if !self
|
||||
.slots
|
||||
.iter()
|
||||
.any(|s| matches!(s, Some(SlotContents::Ability3)))
|
||||
{
|
||||
self.slots[0] = Some(SlotContents::Ability3);
|
||||
}
|
||||
} else {
|
||||
self.slots
|
||||
.iter_mut()
|
||||
.filter(|s| matches!(s, Some(SlotContents::Ability3)))
|
||||
.for_each(|s| *s = None)
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ mod bag;
|
||||
mod buttons;
|
||||
mod chat;
|
||||
mod esc_menu;
|
||||
mod hotbar;
|
||||
mod img_ids;
|
||||
mod item_imgs;
|
||||
mod map;
|
||||
@ -235,6 +236,7 @@ pub enum Event {
|
||||
UseSlot(comp::slot::Slot),
|
||||
SwapSlots(comp::slot::Slot, comp::slot::Slot),
|
||||
DropSlot(comp::slot::Slot),
|
||||
Ability3(bool),
|
||||
Logout,
|
||||
Quit,
|
||||
ChangeLanguage(LanguageMetadata),
|
||||
@ -442,6 +444,8 @@ pub struct Hud {
|
||||
velocity: f32,
|
||||
voxygen_i18n: std::sync::Arc<VoxygenLocalization>,
|
||||
slot_manager: slots::SlotManager,
|
||||
hotbar: hotbar::State,
|
||||
events: Vec<Event>,
|
||||
}
|
||||
|
||||
impl Hud {
|
||||
@ -513,6 +517,8 @@ impl Hud {
|
||||
velocity: 0.0,
|
||||
voxygen_i18n,
|
||||
slot_manager,
|
||||
hotbar: hotbar::State::new(),
|
||||
events: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,7 +535,7 @@ impl Hud {
|
||||
debug_info: DebugInfo,
|
||||
dt: Duration,
|
||||
) -> Vec<Event> {
|
||||
let mut events = Vec::new();
|
||||
let mut events = std::mem::replace(&mut self.events, Vec::new());
|
||||
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
|
||||
// pulse time for pulsating elements
|
||||
self.pulse = self.pulse + dt.as_secs_f32();
|
||||
@ -1676,16 +1682,26 @@ impl Hud {
|
||||
let energies = ecs.read_storage::<comp::Energy>();
|
||||
let character_states = ecs.read_storage::<comp::CharacterState>();
|
||||
let controllers = ecs.read_storage::<comp::Controller>();
|
||||
if let (Some(stats), Some(loadout), Some(energy), Some(character_state), Some(controller)) = (
|
||||
let inventories = ecs.read_storage::<comp::Inventory>();
|
||||
if let (
|
||||
Some(stats),
|
||||
Some(loadout),
|
||||
Some(energy),
|
||||
Some(character_state),
|
||||
Some(controller),
|
||||
Some(inventory),
|
||||
) = (
|
||||
stats.get(entity),
|
||||
loadouts.get(entity),
|
||||
energies.get(entity),
|
||||
character_states.get(entity),
|
||||
controllers.get(entity).map(|c| &c.inputs),
|
||||
inventories.get(entity),
|
||||
) {
|
||||
Skillbar::new(
|
||||
global_state,
|
||||
&self.imgs,
|
||||
&self.item_imgs,
|
||||
&self.fonts,
|
||||
&stats,
|
||||
&loadout,
|
||||
@ -1693,6 +1709,9 @@ impl Hud {
|
||||
&character_state,
|
||||
self.pulse,
|
||||
&controller,
|
||||
&inventory,
|
||||
&self.hotbar,
|
||||
&mut self.slot_manager,
|
||||
)
|
||||
.set(self.ids.skillbar, ui_widgets);
|
||||
}
|
||||
@ -1959,33 +1978,50 @@ impl Hud {
|
||||
// Maintain slot manager
|
||||
for event in self.slot_manager.maintain(ui_widgets) {
|
||||
use comp::slot::Slot;
|
||||
use slots::SlotKind;
|
||||
use slots::SlotKind::*;
|
||||
let to_slot = |slot_kind| match slot_kind {
|
||||
SlotKind::Inventory(i) => Some(Slot::Inventory(i.0)),
|
||||
SlotKind::Equip(e) => Some(Slot::Equip(e)),
|
||||
//SlotKind::Hotbar(h) => None,
|
||||
Inventory(i) => Some(Slot::Inventory(i.0)),
|
||||
Equip(e) => Some(Slot::Equip(e)),
|
||||
Hotbar(_) => None,
|
||||
};
|
||||
match event {
|
||||
slot::Event::Dragged(a, b) => {
|
||||
// Swap between slots
|
||||
if let (Some(a), Some(b)) = (to_slot(a), to_slot(b)) {
|
||||
events.push(Event::SwapSlots(a, b));
|
||||
} else if let (Inventory(i), Hotbar(h)) = (a, b) {
|
||||
self.hotbar.add_inventory_link(h, i.0);
|
||||
} else if let (Hotbar(a), Hotbar(b)) = (a, b) {
|
||||
self.hotbar.swap(a, b);
|
||||
}
|
||||
},
|
||||
slot::Event::Dropped(from) => {
|
||||
// Drop item
|
||||
if let Some(from) = to_slot(from) {
|
||||
events.push(Event::DropSlot(from));
|
||||
} else if let Hotbar(h) = from {
|
||||
self.hotbar.clear_slot(h);
|
||||
}
|
||||
},
|
||||
slot::Event::Used(from) => {
|
||||
// Item used (selected and then clicked again)
|
||||
if let Some(from) = to_slot(from) {
|
||||
events.push(Event::UseSlot(from));
|
||||
} else if let Hotbar(h) = from {
|
||||
self.hotbar.get(h).map(|s| {
|
||||
match s {
|
||||
hotbar::SlotContents::Inventory(i) => {
|
||||
events.push(Event::UseSlot(comp::slot::Slot::Inventory(i)));
|
||||
},
|
||||
hotbar::SlotContents::Ability3 => {}, /* Event::Ability3(true),
|
||||
* sticks */
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
self.hotbar.maintain_ability3(client);
|
||||
|
||||
events
|
||||
}
|
||||
@ -2018,6 +2054,30 @@ impl Hud {
|
||||
}
|
||||
|
||||
pub fn handle_event(&mut self, event: WinEvent, global_state: &mut GlobalState) -> bool {
|
||||
// Helper
|
||||
fn handle_slot(
|
||||
slot: hotbar::Slot,
|
||||
state: bool,
|
||||
events: &mut Vec<Event>,
|
||||
slot_manager: &mut slots::SlotManager,
|
||||
hotbar: &mut hotbar::State,
|
||||
) {
|
||||
if let Some(slots::SlotKind::Inventory(i)) = slot_manager.selected() {
|
||||
hotbar.add_inventory_link(slot, i.0);
|
||||
slot_manager.idle();
|
||||
} else {
|
||||
let just_pressed = hotbar.process_input(slot, state);
|
||||
hotbar.get(slot).map(|s| match s {
|
||||
hotbar::SlotContents::Inventory(i) => {
|
||||
if just_pressed {
|
||||
events.push(Event::UseSlot(comp::slot::Slot::Inventory(i)));
|
||||
}
|
||||
},
|
||||
hotbar::SlotContents::Ability3 => events.push(Event::Ability3(state)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let cursor_grabbed = global_state.window.is_cursor_grabbed();
|
||||
let handled = match event {
|
||||
WinEvent::Ui(event) => {
|
||||
@ -2058,46 +2118,147 @@ impl Hud {
|
||||
},
|
||||
|
||||
// Press key while not typing
|
||||
WinEvent::InputUpdate(key, true) if !self.typing() => match key {
|
||||
GameInput::Command => {
|
||||
WinEvent::InputUpdate(key, state) if !self.typing() => match key {
|
||||
GameInput::Command if state => {
|
||||
self.force_chat_input = Some("/".to_owned());
|
||||
self.force_chat_cursor = Some(Index { line: 0, char: 1 });
|
||||
self.ui.focus_widget(Some(self.ids.chat));
|
||||
true
|
||||
},
|
||||
GameInput::Map => {
|
||||
GameInput::Map if state => {
|
||||
self.show.toggle_map();
|
||||
true
|
||||
},
|
||||
GameInput::Bag => {
|
||||
GameInput::Bag if state => {
|
||||
self.show.toggle_bag();
|
||||
true
|
||||
},
|
||||
GameInput::Social => {
|
||||
GameInput::Social if state => {
|
||||
self.show.toggle_social();
|
||||
true
|
||||
},
|
||||
GameInput::Spellbook => {
|
||||
GameInput::Spellbook if state => {
|
||||
self.show.toggle_spell();
|
||||
true
|
||||
},
|
||||
GameInput::Settings => {
|
||||
GameInput::Settings if state => {
|
||||
self.show.toggle_settings();
|
||||
true
|
||||
},
|
||||
GameInput::Help => {
|
||||
GameInput::Help if state => {
|
||||
self.show.toggle_help();
|
||||
true
|
||||
},
|
||||
GameInput::ToggleDebug => {
|
||||
GameInput::ToggleDebug if state => {
|
||||
global_state.settings.gameplay.toggle_debug =
|
||||
!global_state.settings.gameplay.toggle_debug;
|
||||
true
|
||||
},
|
||||
GameInput::ToggleIngameUi => {
|
||||
GameInput::ToggleIngameUi if state => {
|
||||
self.show.ingame = !self.show.ingame;
|
||||
true
|
||||
},
|
||||
// Skillbar
|
||||
GameInput::Slot1 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::One,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot2 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Two,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot3 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Three,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot4 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Four,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot5 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Five,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot6 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Six,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot7 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Seven,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot8 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Eight,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot9 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Nine,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
GameInput::Slot10 => {
|
||||
handle_slot(
|
||||
hotbar::Slot::Ten,
|
||||
state,
|
||||
&mut self.events,
|
||||
&mut self.slot_manager,
|
||||
&mut self.hotbar,
|
||||
);
|
||||
true
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
// Else the player is typing in chat
|
||||
|
@ -1,10 +1,13 @@
|
||||
use super::{
|
||||
img_ids::Imgs, BarNumbers, ShortcutNumbers, XpBar, BLACK, CRITICAL_HP_COLOR, HP_COLOR,
|
||||
LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR,
|
||||
hotbar, img_ids::Imgs, item_imgs::ItemImgs, slots, BarNumbers, ShortcutNumbers, XpBar, BLACK,
|
||||
CRITICAL_HP_COLOR, HP_COLOR, LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR,
|
||||
};
|
||||
use crate::{
|
||||
i18n::{i18n_asset_key, VoxygenLocalization},
|
||||
ui::fonts::ConrodVoxygenFonts,
|
||||
ui::{
|
||||
fonts::ConrodVoxygenFonts,
|
||||
slot::{ContentSize, SlotMaker},
|
||||
},
|
||||
window::GameInput,
|
||||
GlobalState,
|
||||
};
|
||||
@ -15,7 +18,7 @@ use common::{
|
||||
tool::{DebugKind, StaffKind, Tool, ToolKind},
|
||||
ItemKind,
|
||||
},
|
||||
CharacterState, ControllerInputs, Energy, Loadout, Stats,
|
||||
CharacterState, ControllerInputs, Energy, Inventory, Loadout, Stats,
|
||||
},
|
||||
};
|
||||
use conrod_core::{
|
||||
@ -23,8 +26,8 @@ use conrod_core::{
|
||||
widget::{self, Button, Image, Rectangle, Text},
|
||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
use vek::*;
|
||||
/*
|
||||
use const_tweaker::tweak;
|
||||
#[tweak(min = 0.0, max = 1.0, step = 0.01)]
|
||||
@ -130,12 +133,16 @@ pub enum ResourceType {
|
||||
pub struct Skillbar<'a> {
|
||||
global_state: &'a GlobalState,
|
||||
imgs: &'a Imgs,
|
||||
item_imgs: &'a ItemImgs,
|
||||
fonts: &'a ConrodVoxygenFonts,
|
||||
stats: &'a Stats,
|
||||
loadout: &'a Loadout,
|
||||
energy: &'a Energy,
|
||||
character_state: &'a CharacterState,
|
||||
controller: &'a ControllerInputs,
|
||||
inventory: &'a Inventory,
|
||||
hotbar: &'a hotbar::State,
|
||||
slot_manager: &'a mut slots::SlotManager,
|
||||
pulse: f32,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
@ -146,6 +153,7 @@ impl<'a> Skillbar<'a> {
|
||||
pub fn new(
|
||||
global_state: &'a GlobalState,
|
||||
imgs: &'a Imgs,
|
||||
item_imgs: &'a ItemImgs,
|
||||
fonts: &'a ConrodVoxygenFonts,
|
||||
stats: &'a Stats,
|
||||
loadout: &'a Loadout,
|
||||
@ -153,10 +161,14 @@ impl<'a> Skillbar<'a> {
|
||||
character_state: &'a CharacterState,
|
||||
pulse: f32,
|
||||
controller: &'a ControllerInputs,
|
||||
inventory: &'a Inventory,
|
||||
hotbar: &'a hotbar::State,
|
||||
slot_manager: &'a mut slots::SlotManager,
|
||||
) -> Self {
|
||||
Self {
|
||||
global_state,
|
||||
imgs,
|
||||
item_imgs,
|
||||
fonts,
|
||||
stats,
|
||||
loadout,
|
||||
@ -166,6 +178,9 @@ impl<'a> Skillbar<'a> {
|
||||
character_state,
|
||||
pulse,
|
||||
controller,
|
||||
inventory,
|
||||
hotbar,
|
||||
slot_manager,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -783,51 +798,53 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
},
|
||||
)
|
||||
.set(state.ids.m2_content, ui);
|
||||
// Slots
|
||||
let content_source = (self.hotbar, self.inventory, self.loadout, self.energy); // TODO: avoid this
|
||||
let image_source = (self.item_imgs, self.imgs);
|
||||
|
||||
let mut slot_maker = SlotMaker {
|
||||
// TODO: is a separate image needed for the frame?
|
||||
empty_slot: self.imgs.skillbar_slot,
|
||||
filled_slot: self.imgs.skillbar_slot,
|
||||
selected_slot: self.imgs.skillbar_slot,
|
||||
background_color: Some(BG_COLOR),
|
||||
content_size: ContentSize {
|
||||
width_height_ratio: 1.0,
|
||||
max_fraction: 0.9,
|
||||
},
|
||||
selected_content_scale: 1.067,
|
||||
amount_font: self.fonts.cyri.conrod_id,
|
||||
amount_margins: Vec2::new(-4.0, 0.0),
|
||||
amount_font_size: self.fonts.cyri.scale(12),
|
||||
amount_text_color: TEXT_COLOR,
|
||||
content_source: &content_source,
|
||||
image_source: &image_source,
|
||||
slot_manager: Some(self.slot_manager),
|
||||
};
|
||||
//Slot 5
|
||||
Image::new(self.imgs.skillbar_slot)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Five, [20.0 * scale as f32; 2])
|
||||
.bottom_left_with_margins_on(state.ids.m1_slot, 0.0, -20.0 * scale)
|
||||
.set(state.ids.slot5, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot5)
|
||||
.set(state.ids.slot5_bg, ui);
|
||||
// Slot 4
|
||||
Image::new(self.imgs.skillbar_slot)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Four, [20.0 * scale as f32; 2])
|
||||
.left_from(state.ids.slot5, 0.0)
|
||||
.set(state.ids.slot4, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot4)
|
||||
.set(state.ids.slot4_bg, ui);
|
||||
// Slot 3
|
||||
Image::new(self.imgs.skillbar_slot)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Three, [20.0 * scale as f32; 2])
|
||||
.left_from(state.ids.slot4, 0.0)
|
||||
.set(state.ids.slot3, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot3)
|
||||
.set(state.ids.slot3_bg, ui);
|
||||
// Slot 2
|
||||
Image::new(self.imgs.skillbar_slot)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Two, [20.0 * scale as f32; 2])
|
||||
.left_from(state.ids.slot3, 0.0)
|
||||
.set(state.ids.slot2, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot2)
|
||||
.set(state.ids.slot2_bg, ui);
|
||||
// Slot 1
|
||||
// TODO: Don't hardcode this to one Skill...
|
||||
// Frame flashes whenever the active skill inside this slot is activated
|
||||
match self.character_state {
|
||||
/*
|
||||
/*match self.character_state {
|
||||
CharacterState::Charge { time_left } => {
|
||||
let fade = time_left.as_secs_f32() * 10.0;
|
||||
Image::new(self.imgs.skillbar_slot_l)
|
||||
@ -845,29 +862,14 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
)))
|
||||
.floating(true)
|
||||
.set(state.ids.slot1_act, ui);
|
||||
},*/
|
||||
_ => {
|
||||
Image::new(self.imgs.skillbar_slot_l)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
.left_from(state.ids.slot2, 0.0)
|
||||
.set(state.ids.slot1, ui);
|
||||
},
|
||||
}
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.5 * scale, 19.5 * scale)
|
||||
.color(
|
||||
match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
|
||||
Some(ItemKind::Tool(Tool { kind, .. })) => match kind {
|
||||
ToolKind::Staff(StaffKind::BasicStaff) => Some(BLACK),
|
||||
_ => Some(BG_COLOR),
|
||||
},
|
||||
_ => Some(BG_COLOR),
|
||||
},
|
||||
)
|
||||
.middle_of(state.ids.slot1)
|
||||
.set(state.ids.slot1_bg, ui);
|
||||
}*/
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::One, [20.0 * scale as f32; 2])
|
||||
.left_from(state.ids.slot2, 0.0)
|
||||
.set(state.ids.slot1, ui);
|
||||
// TODO: Changeable slot image
|
||||
match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
|
||||
/*match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
|
||||
Some(ItemKind::Tool(Tool { kind, .. })) => match kind {
|
||||
ToolKind::Staff(StaffKind::BasicStaff) => {
|
||||
Image::new(self.imgs.fire_spell_1)
|
||||
@ -883,65 +885,43 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
_ => {},
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}*/
|
||||
// Slot 6
|
||||
Image::new(self.imgs.skillbar_slot)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Six, [20.0 * scale as f32; 2])
|
||||
.bottom_right_with_margins_on(state.ids.m2_slot, 0.0, -20.0 * scale)
|
||||
.set(state.ids.slot6, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot6)
|
||||
.set(state.ids.slot6_bg, ui);
|
||||
// Slot 7
|
||||
Image::new(self.imgs.skillbar_slot)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Seven, [20.0 * scale as f32; 2])
|
||||
.right_from(state.ids.slot6, 0.0)
|
||||
.set(state.ids.slot7, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot7)
|
||||
.set(state.ids.slot7_bg, ui);
|
||||
// Slot 8
|
||||
Image::new(self.imgs.skillbar_slot)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Eight, [20.0 * scale as f32; 2])
|
||||
.right_from(state.ids.slot7, 0.0)
|
||||
.set(state.ids.slot8, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot8)
|
||||
.set(state.ids.slot8_bg, ui);
|
||||
// Slot 9
|
||||
Image::new(self.imgs.skillbar_slot)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Nine, [20.0 * scale as f32; 2])
|
||||
.right_from(state.ids.slot8, 0.0)
|
||||
.set(state.ids.slot9, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot9)
|
||||
.set(state.ids.slot9_bg, ui);
|
||||
// Quickslot
|
||||
Image::new(self.imgs.skillbar_slot_r)
|
||||
.w_h(20.0 * scale, 20.0 * scale)
|
||||
slot_maker.filled_slot = self.imgs.skillbar_slot_r;
|
||||
slot_maker.selected_slot = self.imgs.skillbar_slot_r;
|
||||
slot_maker.empty_slot = self.imgs.skillbar_slot_r;
|
||||
slot_maker
|
||||
.fabricate(hotbar::Slot::Ten, [20.0 * scale as f32; 2])
|
||||
.right_from(state.ids.slot9, 0.0)
|
||||
.set(state.ids.slot10, ui);
|
||||
Image::new(self.imgs.skillbar_slot_bg)
|
||||
.w_h(19.0 * scale, 19.0 * scale)
|
||||
.color(Some(BG_COLOR))
|
||||
.middle_of(state.ids.slot10)
|
||||
.set(state.ids.slot10_bg, ui);
|
||||
// Shortcuts
|
||||
|
||||
// Shortcuts
|
||||
if let ShortcutNumbers::On = shortcuts {
|
||||
if let Some(slot1) = &self
|
||||
.global_state
|
||||
.settings
|
||||
.controls
|
||||
.get_binding(GameInput::Ability3)
|
||||
.get_binding(GameInput::Slot1)
|
||||
{
|
||||
Text::new(slot1.to_string().as_str())
|
||||
.top_right_with_margins_on(state.ids.slot1_bg, 1.0, 2.0)
|
||||
|
@ -1,7 +1,11 @@
|
||||
use super::item_imgs::{ItemImgs, ItemKey};
|
||||
use super::{
|
||||
hotbar::{self, Slot as HotbarSlot},
|
||||
img_ids,
|
||||
item_imgs::{ItemImgs, ItemKey},
|
||||
};
|
||||
use crate::ui::slot::{self, SlotKey, SumSlot};
|
||||
use common::comp::{item::ItemKind, Inventory, Loadout};
|
||||
use conrod_core::image;
|
||||
use common::comp::{item::ItemKind, Energy, Inventory, Loadout};
|
||||
use conrod_core::{image, Color};
|
||||
|
||||
pub use common::comp::slot::{ArmorSlot, EquipSlot};
|
||||
|
||||
@ -9,8 +13,8 @@ pub use common::comp::slot::{ArmorSlot, EquipSlot};
|
||||
pub enum SlotKind {
|
||||
Inventory(InventorySlot),
|
||||
Equip(EquipSlot),
|
||||
/*Hotbar(HotbarSlot),
|
||||
*Spellbook(SpellbookSlot), TODO */
|
||||
Hotbar(HotbarSlot),
|
||||
/* Spellbook(SpellbookSlot), TODO */
|
||||
}
|
||||
|
||||
pub type SlotManager = slot::SlotManager<SlotKind>;
|
||||
@ -18,25 +22,11 @@ pub type SlotManager = slot::SlotManager<SlotKind>;
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct InventorySlot(pub usize);
|
||||
|
||||
/*#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum HotbarSlot {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine,
|
||||
Ten,
|
||||
}*/
|
||||
|
||||
impl SlotKey<Inventory, ItemImgs> for InventorySlot {
|
||||
type ImageKey = ItemKey;
|
||||
|
||||
fn image_key(&self, source: &Inventory) -> Option<Self::ImageKey> {
|
||||
source.get(self.0).map(Into::into)
|
||||
fn image_key(&self, source: &Inventory) -> Option<(Self::ImageKey, Option<Color>)> {
|
||||
source.get(self.0).map(|i| (i.into(), None))
|
||||
}
|
||||
|
||||
fn amount(&self, source: &Inventory) -> Option<u32> {
|
||||
@ -59,7 +49,7 @@ impl SlotKey<Inventory, ItemImgs> for InventorySlot {
|
||||
impl SlotKey<Loadout, ItemImgs> for EquipSlot {
|
||||
type ImageKey = ItemKey;
|
||||
|
||||
fn image_key(&self, source: &Loadout) -> Option<Self::ImageKey> {
|
||||
fn image_key(&self, source: &Loadout) -> Option<(Self::ImageKey, Option<Color>)> {
|
||||
let item = match self {
|
||||
EquipSlot::Armor(ArmorSlot::Shoulders) => source.shoulder.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Chest) => source.chest.as_ref(),
|
||||
@ -77,7 +67,7 @@ impl SlotKey<Loadout, ItemImgs> for EquipSlot {
|
||||
EquipSlot::Lantern => source.lantern.as_ref(),
|
||||
};
|
||||
|
||||
item.map(Into::into)
|
||||
item.map(|i| (i.into(), None))
|
||||
}
|
||||
|
||||
fn amount(&self, _: &Loadout) -> Option<u32> { None }
|
||||
@ -87,18 +77,58 @@ impl SlotKey<Loadout, ItemImgs> for EquipSlot {
|
||||
}
|
||||
}
|
||||
|
||||
/*impl SlotKey<Hotbar, ItemImgs> for HotbarSlot {
|
||||
type ImageKey = ItemKey;
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum HotbarImage {
|
||||
Item(ItemKey),
|
||||
Ability3,
|
||||
}
|
||||
|
||||
fn image_key(&self, source: &Inventory) -> Option<Self::ImageKey> {
|
||||
source.get(self.0).map(Into::into)
|
||||
type HotbarSource<'a> = (&'a hotbar::State, &'a Inventory, &'a Loadout, &'a Energy);
|
||||
type HotbarImageSource<'a> = (&'a ItemImgs, &'a img_ids::Imgs);
|
||||
|
||||
impl<'a> SlotKey<HotbarSource<'a>, HotbarImageSource<'a>> for HotbarSlot {
|
||||
type ImageKey = HotbarImage;
|
||||
|
||||
fn image_key(
|
||||
&self,
|
||||
(hotbar, inventory, loadout, energy): &HotbarSource<'a>,
|
||||
) -> Option<(Self::ImageKey, Option<Color>)> {
|
||||
hotbar.get(*self).and_then(|contents| match contents {
|
||||
hotbar::SlotContents::Inventory(idx) => inventory
|
||||
.get(idx)
|
||||
.map(|item| HotbarImage::Item(item.into()))
|
||||
.map(|i| (i, None)),
|
||||
hotbar::SlotContents::Ability3 => loadout
|
||||
.active_item
|
||||
.as_ref()
|
||||
.map(|i| &i.item.kind)
|
||||
.and_then(|kind| {
|
||||
use common::comp::item::tool::{StaffKind, Tool, ToolKind};
|
||||
matches!(
|
||||
kind,
|
||||
ItemKind::Tool(Tool {
|
||||
kind: ToolKind::Staff(StaffKind::BasicStaff),
|
||||
..
|
||||
})
|
||||
)
|
||||
.then_some((
|
||||
HotbarImage::Ability3,
|
||||
// Darken if not enough energy to use attack
|
||||
(energy.current() < 500).then_some(Color::Rgba(0.3, 0.3, 0.3, 0.8)),
|
||||
))
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
fn amount(&self, source: &Inventory) -> Option<u32> {
|
||||
source
|
||||
.get(self.0)
|
||||
fn amount(&self, (hotbar, inventory, _, _): &HotbarSource<'a>) -> Option<u32> {
|
||||
hotbar
|
||||
.get(*self)
|
||||
.and_then(|content| match content {
|
||||
hotbar::SlotContents::Inventory(idx) => inventory.get(idx),
|
||||
hotbar::SlotContents::Ability3 => None,
|
||||
})
|
||||
.and_then(|item| match item.kind {
|
||||
ItemKind::Tool { .. } | ItemKind::Armor { .. } => None,
|
||||
ItemKind::Tool { .. } | ItemKind::Lantern(_) | ItemKind::Armor { .. } => None,
|
||||
ItemKind::Utility { amount, .. }
|
||||
| ItemKind::Consumable { amount, .. }
|
||||
| ItemKind::Ingredient { amount, .. } => Some(amount),
|
||||
@ -106,10 +136,13 @@ impl SlotKey<Loadout, ItemImgs> for EquipSlot {
|
||||
.filter(|amount| *amount > 1)
|
||||
}
|
||||
|
||||
fn image_id(key: &Self::ImageKey, source: &ItemImgs) -> image::Id {
|
||||
source.img_id_or_not_found_img(key.clone())
|
||||
fn image_id(key: &Self::ImageKey, (item_imgs, imgs): &HotbarImageSource<'a>) -> image::Id {
|
||||
match key {
|
||||
HotbarImage::Item(key) => item_imgs.img_id_or_not_found_img(key.clone()),
|
||||
HotbarImage::Ability3 => imgs.fire_spell_1,
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
impl From<InventorySlot> for SlotKind {
|
||||
fn from(inventory: InventorySlot) -> Self { Self::Inventory(inventory) }
|
||||
@ -119,8 +152,8 @@ impl From<EquipSlot> for SlotKind {
|
||||
fn from(equip: EquipSlot) -> Self { Self::Equip(equip) }
|
||||
}
|
||||
|
||||
//impl From<HotbarSlot> for SlotKind {
|
||||
// fn from(hotbar: HotbarSlot) -> Self { Self::Hotbar(hotbar) }
|
||||
//}
|
||||
impl From<HotbarSlot> for SlotKind {
|
||||
fn from(hotbar: HotbarSlot) -> Self { Self::Hotbar(hotbar) }
|
||||
}
|
||||
|
||||
impl SumSlot for SlotKind {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(drain_filter, bool_to_option)]
|
||||
#![recursion_limit = "2048"]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -282,9 +282,6 @@ impl PlayState for SessionState {
|
||||
}
|
||||
},
|
||||
|
||||
Event::InputUpdate(GameInput::Ability3, state) => {
|
||||
self.inputs.ability3.set_state(state);
|
||||
},
|
||||
Event::InputUpdate(GameInput::Roll, state) => {
|
||||
let client = self.client.borrow();
|
||||
if client
|
||||
@ -646,6 +643,7 @@ impl PlayState for SessionState {
|
||||
HudEvent::UseSlot(x) => self.client.borrow_mut().use_slot(x),
|
||||
HudEvent::SwapSlots(a, b) => self.client.borrow_mut().swap_slots(a, b),
|
||||
HudEvent::DropSlot(x) => self.client.borrow_mut().drop_slot(x),
|
||||
HudEvent::Ability3(state) => self.inputs.ability3.set_state(state),
|
||||
HudEvent::ChangeFOV(new_fov) => {
|
||||
global_state.settings.graphics.fov = new_fov;
|
||||
global_state.settings.save_to_file_warn();
|
||||
|
@ -138,7 +138,7 @@ impl ControlSettings {
|
||||
GameInput::ToggleWield => KeyMouse::Key(VirtualKeyCode::T),
|
||||
//GameInput::Charge => KeyMouse::Key(VirtualKeyCode::Key1),
|
||||
GameInput::FreeLook => KeyMouse::Key(VirtualKeyCode::L),
|
||||
GameInput::Ability3 => KeyMouse::Key(VirtualKeyCode::Key1),
|
||||
GameInput::Slot1 => KeyMouse::Key(VirtualKeyCode::Key1),
|
||||
GameInput::Slot2 => KeyMouse::Key(VirtualKeyCode::Key2),
|
||||
GameInput::Slot3 => KeyMouse::Key(VirtualKeyCode::Key3),
|
||||
GameInput::Slot4 => KeyMouse::Key(VirtualKeyCode::Key4),
|
||||
@ -196,7 +196,7 @@ impl Default for ControlSettings {
|
||||
GameInput::ToggleWield,
|
||||
//GameInput::Charge,
|
||||
GameInput::FreeLook,
|
||||
GameInput::Ability3,
|
||||
GameInput::Slot1,
|
||||
GameInput::Slot2,
|
||||
GameInput::Slot3,
|
||||
GameInput::Slot4,
|
||||
|
@ -13,7 +13,7 @@ const AMOUNT_SHADOW_OFFSET: [f64; 2] = [1.0, 1.0];
|
||||
pub trait SlotKey<C, I>: Copy {
|
||||
type ImageKey: PartialEq + Send + 'static;
|
||||
/// Returns an Option since the slot could be empty
|
||||
fn image_key(&self, source: &C) -> Option<Self::ImageKey>;
|
||||
fn image_key(&self, source: &C) -> Option<(Self::ImageKey, Option<Color>)>;
|
||||
fn amount(&self, source: &C) -> Option<u32>;
|
||||
fn image_id(key: &Self::ImageKey, source: &I) -> image::Id;
|
||||
}
|
||||
@ -285,6 +285,18 @@ where
|
||||
_ => Interaction::None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns Some(slot) if a slot is selected
|
||||
pub fn selected(&self) -> Option<S> {
|
||||
if let ManagerState::Selected(_, s) = self.state {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the SlotManager into an idle state
|
||||
pub fn idle(&mut self) { self.state = ManagerState::Idle; }
|
||||
}
|
||||
|
||||
#[derive(WidgetCommon)]
|
||||
@ -435,7 +447,9 @@ where
|
||||
} = self;
|
||||
|
||||
// If the key changed update the cached image id
|
||||
let image_key = slot_key.image_key(content_source);
|
||||
let (image_key, content_color) = slot_key
|
||||
.image_key(content_source)
|
||||
.map_or((None, None), |(i, c)| (Some(i), c));
|
||||
if state.cached_image.as_ref().map(|c| &c.0) != image_key.as_ref() {
|
||||
state.update(|state| {
|
||||
state.cached_image = image_key.map(|key| {
|
||||
@ -510,6 +524,7 @@ where
|
||||
})
|
||||
.map(|e| e as f64)
|
||||
.into_array())
|
||||
.color(content_color)
|
||||
.parent(id)
|
||||
.graphics_for(id)
|
||||
.set(state.ids.content, ui);
|
||||
|
@ -17,7 +17,7 @@ use vek::*;
|
||||
pub enum GameInput {
|
||||
Primary,
|
||||
Secondary,
|
||||
Ability3,
|
||||
Slot1,
|
||||
Slot2,
|
||||
Slot3,
|
||||
Slot4,
|
||||
@ -99,7 +99,7 @@ impl GameInput {
|
||||
GameInput::ToggleWield => "gameinput.togglewield",
|
||||
//GameInput::Charge => "gameinput.charge",
|
||||
GameInput::FreeLook => "gameinput.freelook",
|
||||
GameInput::Ability3 => "gameinput.slot1",
|
||||
GameInput::Slot1 => "gameinput.slot1",
|
||||
GameInput::Slot2 => "gameinput.slot2",
|
||||
GameInput::Slot3 => "gameinput.slot3",
|
||||
GameInput::Slot4 => "gameinput.slot4",
|
||||
|
Loading…
Reference in New Issue
Block a user