Split Skillbar::update to separate stages

This commit is contained in:
juliancoffee 2021-07-22 22:57:04 +03:00
parent 930a156cab
commit 4811ede2ea
2 changed files with 195 additions and 179 deletions

View File

@ -316,6 +316,40 @@ widget_ids! {
}
}
// TODO: extend as you need it
#[derive(Clone, Copy)]
pub enum PositionSpecifier {
MidBottomWithMarginOn(widget::Id, f64),
TopRightWithMarginsOn(widget::Id, f64, f64),
BottomRightWithMarginsOn(widget::Id, f64, f64),
BottomLeftWithMarginsOn(widget::Id, f64, f64),
RightFrom(widget::Id, f64),
}
pub trait Position {
fn position(self, request: PositionSpecifier) -> Self;
}
impl<W: Positionable> Position for W {
fn position(self, request: PositionSpecifier) -> Self {
match request {
PositionSpecifier::MidBottomWithMarginOn(other, margin) => {
self.mid_bottom_with_margin_on(other, margin)
},
PositionSpecifier::TopRightWithMarginsOn(other, top, right) => {
self.top_right_with_margins_on(other, top, right)
},
PositionSpecifier::BottomRightWithMarginsOn(other, bottom, right) => {
self.bottom_right_with_margins_on(other, bottom, right)
},
PositionSpecifier::BottomLeftWithMarginsOn(other, bottom, left) => {
self.bottom_left_with_margins_on(other, bottom, left)
},
PositionSpecifier::RightFrom(other, offset) => self.right_from(other, offset),
}
}
}
#[derive(Clone, Copy)]
pub struct BuffInfo {
kind: comp::BuffKind,

View File

@ -7,7 +7,7 @@ use super::{
};
use crate::{
game_input::GameInput,
hud::ComboFloater,
hud::{ComboFloater, Position, PositionSpecifier},
i18n::Localization,
ui::{
fonts::Fonts,
@ -132,41 +132,6 @@ widget_ids! {
}
}
// TODO: extend as you need it
// Make it public to use throughout the code?
#[derive(Clone, Copy)]
enum PositionSpecifier {
MidBottomWithMarginOn(widget::Id, f64),
TopRightWithMarginsOn(widget::Id, f64, f64),
BottomRightWithMarginsOn(widget::Id, f64, f64),
BottomLeftWithMarginsOn(widget::Id, f64, f64),
RightFrom(widget::Id, f64),
}
trait Position {
fn position(self, request: PositionSpecifier) -> Self;
}
impl<W: Positionable> Position for W {
fn position(self, request: PositionSpecifier) -> Self {
match request {
PositionSpecifier::MidBottomWithMarginOn(other, margin) => {
self.mid_bottom_with_margin_on(other, margin)
},
PositionSpecifier::TopRightWithMarginsOn(other, top, right) => {
self.top_right_with_margins_on(other, top, right)
},
PositionSpecifier::BottomRightWithMarginsOn(other, bottom, right) => {
self.bottom_right_with_margins_on(other, bottom, right)
},
PositionSpecifier::BottomLeftWithMarginsOn(other, bottom, left) => {
self.bottom_left_with_margins_on(other, bottom, left)
},
PositionSpecifier::RightFrom(other, offset) => self.right_from(other, offset),
}
}
}
#[derive(Clone, Copy)]
struct SlotEntry {
slot: hotbar::Slot,
@ -351,54 +316,11 @@ impl<'a> Skillbar<'a> {
combo,
}
}
}
pub struct State {
ids: Ids,
}
impl<'a> Widget for Skillbar<'a> {
type Event = ();
type State = State;
type Style = ();
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
State {
ids: Ids::new(id_gen),
}
}
fn style(&self) -> Self::Style {}
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
common_base::prof_span!("Skillbar::update");
let widget::UpdateArgs { state, ui, .. } = args;
let (hp_percentage, energy_percentage): (f64, f64) = if self.health.is_dead {
(0.0, 0.0)
} else {
let max_hp = cmp::max(self.health.base_max(), self.health.maximum()) as f64;
let current_hp = self.health.current() as f64;
(
current_hp / max_hp * 100.0,
(self.energy.fraction() * 100.0).into(),
)
};
let bar_values = self.global_state.settings.interface.bar_numbers;
let shortcuts = self.global_state.settings.interface.shortcut_numbers;
// Animation timer
let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8;
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
fn show_death_message(&self, state: &State, ui: &mut UiCell) {
let localized_strings = self.localized_strings;
let key_layout = &self.global_state.window.key_layout;
let slot_offset = 3.0;
// Death message
if self.health.is_dead {
if let Some(key) = self
.global_state
.settings
@ -439,13 +361,23 @@ impl<'a> Widget for Skillbar<'a> {
.set(state.ids.death_message_2, ui);
}
}
// Skillbar
// Alignment and BG
let alignment_size = 40.0 * 12.0 + slot_offset * 11.0;
Rectangle::fill_with([alignment_size, 80.0], color::TRANSPARENT)
.mid_bottom_with_margin_on(ui.window, 10.0)
.set(state.ids.frame, ui);
// Health and Stamina bar
fn show_stat_bars(&self, state: &State, ui: &mut UiCell) {
let (hp_percentage, energy_percentage): (f64, f64) = if self.health.is_dead {
(0.0, 0.0)
} else {
let max_hp = cmp::max(self.health.base_max(), self.health.maximum()) as f64;
let current_hp = self.health.current() as f64;
(
current_hp / max_hp * 100.0,
(self.energy.fraction() * 100.0).into(),
)
};
// Animation timer
let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8;
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
let bar_values = self.global_state.settings.interface.bar_numbers;
let show_health = self.health.current() != self.health.maximum();
let show_stamina = self.energy.current() != self.energy.maximum();
let decayed_health = 1.0 - self.health.maximum() as f64 / self.health.base_max() as f64;
@ -517,32 +449,6 @@ impl<'a> Widget for Skillbar<'a> {
.set(state.ids.frame_stamina, ui);
}
// Bar Text
let show_bar_text = |hp_txt: &str, energy_txt: &str, ui: &mut UiCell| {
Text::new(hp_txt)
.middle_of(state.ids.frame_health)
.font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
.set(state.ids.hp_txt_bg, ui);
Text::new(hp_txt)
.bottom_left_with_margins_on(state.ids.hp_txt_bg, 2.0, 2.0)
.font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.hp_txt, ui);
Text::new(energy_txt)
.middle_of(state.ids.frame_stamina)
.font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
.set(state.ids.stamina_txt_bg, ui);
Text::new(energy_txt)
.bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0)
.font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.stamina_txt, ui);
};
let bar_text = if self.health.is_dead {
Some((
self.localized_strings.get("hud.group.dead").to_owned(),
@ -571,12 +477,41 @@ impl<'a> Widget for Skillbar<'a> {
None
};
if let Some((hp_txt, energy_txt)) = bar_text {
show_bar_text(&hp_txt, &energy_txt, ui);
Text::new(&hp_txt)
.middle_of(state.ids.frame_health)
.font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
.set(state.ids.hp_txt_bg, ui);
Text::new(&hp_txt)
.bottom_left_with_margins_on(state.ids.hp_txt_bg, 2.0, 2.0)
.font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.hp_txt, ui);
Text::new(&energy_txt)
.middle_of(state.ids.frame_stamina)
.font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
.set(state.ids.stamina_txt_bg, ui);
Text::new(&energy_txt)
.bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0)
.font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.stamina_txt, ui);
}
}
// Slots
fn show_slotbar(&mut self, state: &State, ui: &mut UiCell, slot_offset: f64) {
let shortcuts = self.global_state.settings.interface.shortcut_numbers;
let key_layout = &self.global_state.window.key_layout;
// TODO: avoid this
let content_source = (self.hotbar, self.inventory, self.energy, self.skillset);
let image_source = (self.item_imgs, self.imgs);
let mut slot_maker = SlotMaker {
// TODO: is a separate image needed for the frame?
@ -700,6 +635,7 @@ impl<'a> Widget for Skillbar<'a> {
slot_maker.empty_slot = self.imgs.skillbar_slot;
slot_maker.selected_slot = self.imgs.skillbar_slot;
let slots = slot_entries(state, slot_offset);
for entry in slots {
let slot = slot_maker
@ -859,9 +795,9 @@ impl<'a> Widget for Skillbar<'a> {
.w_h(16.0, 18.0)
.mid_bottom_with_margin_on(state.ids.m2_content, -11.0)
.set(state.ids.m2_ico, ui);
}
// Combo Counter
if let Some(combo) = self.combo {
fn show_combo_counter(&self, combo: ComboFloater, state: &State, ui: &mut UiCell) {
if combo.combo > 0 {
let combo_txt = format!("{} Combo", combo.combo);
let combo_cnt = combo.combo as f32;
@ -878,29 +814,75 @@ impl<'a> Widget for Skillbar<'a> {
// "flash" on update by increasing the font size by 2.
let fnt_size = ((14.0 + combo.timer as f32 * 0.8).min(30.0)) as u32
+ if (time_since_last_update) < 0.1 { 2 } else { 0 };
Rectangle::fill_with([10.0, 10.0], color::TRANSPARENT)
.middle_of(ui.window)
.set(state.ids.combo_align, ui);
let bg_align = PositionSpecifier::MidBottomWithMarginOn(
Text::new(combo_txt.as_str())
.mid_bottom_with_margin_on(
state.ids.combo_align,
-350.0 + time_since_last_update * -8.0,
);
let align =
PositionSpecifier::BottomRightWithMarginsOn(state.ids.combo_bg, 1.0, 1.0);
Text::new(combo_txt.as_str())
.position(bg_align)
)
.font_size(self.fonts.cyri.scale(fnt_size))
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, alpha))
.set(state.ids.combo_bg, ui);
Text::new(combo_txt.as_str())
.position(align)
.bottom_right_with_margins_on(state.ids.combo_bg, 1.0, 1.0)
.font_size(self.fonts.cyri.scale(fnt_size))
.font_id(self.fonts.cyri.conrod_id)
.color(fnt_col)
.set(state.ids.combo, ui);
}
}
}
pub struct State {
ids: Ids,
}
impl<'a> Widget for Skillbar<'a> {
type Event = ();
type State = State;
type Style = ();
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
State {
ids: Ids::new(id_gen),
}
}
fn style(&self) -> Self::Style {}
fn update(mut self, args: widget::UpdateArgs<Self>) -> Self::Event {
common_base::prof_span!("Skillbar::update");
let widget::UpdateArgs { state, ui, .. } = args;
let slot_offset = 3.0;
// Death message
if self.health.is_dead {
self.show_death_message(state, ui);
}
// Skillbar
// Alignment and BG
let alignment_size = 40.0 * 12.0 + slot_offset * 11.0;
Rectangle::fill_with([alignment_size, 80.0], color::TRANSPARENT)
.mid_bottom_with_margin_on(ui.window, 10.0)
.set(state.ids.frame, ui);
// Health and Stamina bar
self.show_stat_bars(state, ui);
// Slots
self.show_slotbar(state, ui, slot_offset);
// Combo Counter
if let Some(combo) = self.combo {
self.show_combo_counter(combo, state, ui);
}
}
}