Merge branch 'pfau/bag_icon' into 'master'

Bag icon improvement

See merge request veloren/veloren!3731
This commit is contained in:
Monty Marz 2022-12-23 15:22:14 +00:00
commit b19d02f7e9
14 changed files with 266 additions and 230 deletions

View File

@ -55,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Item pickup UI now displays items that members of your group pick up.
- Improved shiny water shaders
- Tweaked armor stats
- Move bag icon to skillbar
### Removed

BIN
assets/voxygen/element/ui/generic/buttons/bag.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/ui/generic/buttons/spellbook0.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/ui/skillbar/bag_frame.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,28 +1,20 @@
use super::{
img_ids::{Imgs, ImgsRot},
HudInfo, BLACK, CRITICAL_HP_COLOR, LOW_HP_COLOR, QUALITY_LEGENDARY, TEXT_COLOR,
BLACK, TEXT_COLOR,
};
use crate::{
game_input::GameInput,
hud::animation::animation_timer,
ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable},
window::KeyMouse,
GlobalState,
};
use client::Client;
use common::comp::{SkillSet, Stats};
use conrod_core::{
widget::{self, Button, Image, Text, UpdateArgs},
widget::{self, Button, Text, UpdateArgs},
widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, WidgetCommon,
};
use i18n::Localization;
widget_ids! {
struct Ids {
bag,
bag_text,
bag_text_bg,
bag_space,
bag_space_bg,
bag_show_map,
map_button,
map_text,
@ -50,9 +42,6 @@ widget_ids! {
}
#[derive(WidgetCommon)]
pub struct Buttons<'a> {
client: &'a Client,
info: &'a HudInfo,
show_bag: bool,
imgs: &'a Imgs,
fonts: &'a Fonts,
#[conrod(common_builder)]
@ -61,30 +50,18 @@ pub struct Buttons<'a> {
rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager,
localized_strings: &'a Localization,
stats: &'a Stats,
skill_set: &'a SkillSet,
pulse: f32,
}
impl<'a> Buttons<'a> {
pub fn new(
client: &'a Client,
info: &'a HudInfo,
show_bag: bool,
imgs: &'a Imgs,
fonts: &'a Fonts,
global_state: &'a GlobalState,
rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager,
localized_strings: &'a Localization,
stats: &'a Stats,
skill_set: &'a SkillSet,
pulse: f32,
) -> Self {
Self {
client,
info,
show_bag,
imgs,
fonts,
common: widget::CommonBuilder::default(),
@ -92,9 +69,6 @@ impl<'a> Buttons<'a> {
rot_imgs,
tooltip_manager,
localized_strings,
stats,
skill_set,
pulse,
}
}
}
@ -105,11 +79,9 @@ pub struct State {
#[allow(clippy::enum_variant_names)] //think about renaming to ToggleEvent
pub enum Event {
ToggleBag,
ToggleSettings,
ToggleMap,
ToggleSocial,
ToggleSpell,
ToggleCrafting,
}
@ -148,85 +120,11 @@ impl<'a> Widget for Buttons<'a> {
.desc_font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.desc_text_color(TEXT_COLOR);
// Bag
if Button::image(if !self.show_bag {
self.imgs.bag
} else {
self.imgs.bag_open
})
.bottom_right_with_margins_on(ui.window, 5.0, 5.0)
.hover_image(if !self.show_bag {
self.imgs.bag_hover
} else {
self.imgs.bag_open_hover
})
.press_image(if !self.show_bag {
self.imgs.bag_press
} else {
self.imgs.bag_open_press
})
.w_h(420.0 / 10.0, 480.0 / 10.0)
.with_tooltip(
self.tooltip_manager,
&localized_strings.get_msg_ctx("hud-bag-inventory", &i18n::fluent_args! {
"playername" => &self.stats.name
}),
"",
&button_tooltip,
TEXT_COLOR,
)
.set(state.ids.bag, ui)
.was_clicked()
{
return Some(Event::ToggleBag);
};
if let Some(bag) = &self
.global_state
.settings
.controls
.get_binding(GameInput::Bag)
{
self.create_new_button_with_shadow(
ui,
bag,
state.ids.bag,
state.ids.bag_text_bg,
state.ids.bag_text,
);
}
let invs = self.client.inventories();
let inventory = match invs.get(self.info.viewpoint_entity) {
Some(inv) => inv,
None => return None,
};
if !self.show_bag {
let space_used = inventory.populated_slots();
let space_max = inventory.slots().count();
let bag_space = format!("{}/{}", space_used, space_max);
let bag_space_percentage = space_used as f32 / space_max as f32;
Text::new(&bag_space)
.mid_top_with_margin_on(state.ids.bag, -15.0)
.font_size(12)
.font_id(self.fonts.cyri.conrod_id)
.color(BLACK)
.set(state.ids.bag_space_bg, ui);
Text::new(&bag_space)
.top_left_with_margins_on(state.ids.bag_space_bg, -1.0, -1.0)
.font_size(12)
.font_id(self.fonts.cyri.conrod_id)
.color(if bag_space_percentage < 0.8 {
TEXT_COLOR
} else if bag_space_percentage < 1.0 {
LOW_HP_COLOR
} else {
CRITICAL_HP_COLOR
})
.set(state.ids.bag_space, ui);
}
// Settings
if Button::image(self.imgs.settings)
.w_h(29.0, 25.0)
.bottom_right_with_margins_on(ui.window, 5.0, 57.0)
.bottom_right_with_margins_on(ui.window, 5.0, 5.0)
.hover_image(self.imgs.settings_hover)
.press_image(self.imgs.settings_press)
.with_tooltip(
@ -320,71 +218,11 @@ impl<'a> Widget for Buttons<'a> {
state.ids.map_text,
);
}
// Diary
let unspent_sp = self.skill_set.has_available_sp();
if Button::image(if !unspent_sp {
self.imgs.spellbook_button
} else {
self.imgs.spellbook_hover
})
.w_h(28.0, 25.0)
.left_from(state.ids.map_button, 10.0)
.hover_image(self.imgs.spellbook_hover)
.press_image(self.imgs.spellbook_press)
.with_tooltip(
self.tooltip_manager,
&localized_strings.get_msg("hud-diary"),
"",
&button_tooltip,
TEXT_COLOR,
)
.set(state.ids.spellbook_button, ui)
.was_clicked()
{
return Some(Event::ToggleSpell);
}
if let Some(spell) = &self
.global_state
.settings
.controls
.get_binding(GameInput::Spellbook)
{
self.create_new_button_with_shadow(
ui,
spell,
state.ids.spellbook_button,
state.ids.spellbook_text_bg,
state.ids.spellbook_text,
);
}
// Unspent SP indicator
if unspent_sp {
let arrow_ani = animation_timer(self.pulse); //Animation timer
Image::new(self.imgs.sp_indicator_arrow)
.w_h(20.0, 11.0)
.graphics_for(state.ids.spellbook_button)
.mid_top_with_margin_on(state.ids.spellbook_button, -12.0 + arrow_ani as f64)
.color(Some(QUALITY_LEGENDARY))
.set(state.ids.sp_arrow, ui);
Text::new(&localized_strings.get_msg("hud-sp_arrow_txt"))
.mid_top_with_margin_on(state.ids.sp_arrow, -18.0)
.graphics_for(state.ids.spellbook_button)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.color(BLACK)
.set(state.ids.sp_arrow_txt_bg, ui);
Text::new(&localized_strings.get_msg("hud-sp_arrow_txt"))
.graphics_for(state.ids.spellbook_button)
.bottom_right_with_margins_on(state.ids.sp_arrow_txt_bg, 1.0, 1.0)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.color(QUALITY_LEGENDARY)
.set(state.ids.sp_arrow_txt, ui);
}
// Crafting
if Button::image(self.imgs.crafting_icon)
.w_h(25.0, 25.0)
.left_from(state.ids.spellbook_button, 10.0)
.left_from(state.ids.map_button, 10.0)
.hover_image(self.imgs.crafting_icon_hover)
.press_image(self.imgs.crafting_icon_press)
.with_tooltip(

View File

@ -94,6 +94,7 @@ image_ids! {
pickaxe_ico: "voxygen.element.weapons.pickaxe",
skilltree_ico: "voxygen.element.ui.diary.buttons.skilltree",
spellbook_ico: "voxygen.element.ui.diary.buttons.spellbook",
spellbook_ico0: "voxygen.element.ui.generic.buttons.spellbook0",
stats_ico: "voxygen.element.ui.diary.buttons.stats",
lock: "voxygen.element.ui.diary.buttons.lock",
wpn_icon_border_skills: "voxygen.element.ui.diary.buttons.border_skills",
@ -370,6 +371,7 @@ image_ids! {
exp_frame: "voxygen.element.ui.skillbar.exp_frame",
exp_frame_bg: "voxygen.element.ui.skillbar.exp_frame_bg",
selected_exp: "voxygen.element.ui.skillbar.selected_exp_frame",
bag_frame: "voxygen.element.ui.skillbar.bag_frame",
selected_exp_bg: "voxygen.element.ui.skillbar.selected_exp_frame_bg",
decayed_bg: "voxygen.element.ui.skillbar.decayed_bg",
energy_bg: "voxygen.element.ui.skillbar.energy_bg",
@ -383,6 +385,7 @@ image_ids! {
m_move_ico: "voxygen.element.ui.generic.icons.m_move",
m_click_ico: "voxygen.element.ui.generic.icons.m_click",
skillbar_slot: "voxygen.element.ui.skillbar.slot",
bag_ico: "voxygen.element.ui.generic.buttons.bag",
// Other Icons/Art
@ -614,14 +617,6 @@ image_ids! {
// Enemy Bar Content:
enemy_bar: "voxygen.element.ui.skillbar.enemy_bar_content",
// Bag
bag: "voxygen.element.ui.generic.buttons.bag.closed",
bag_hover: "voxygen.element.ui.generic.buttons.bag.closed_hover",
bag_press: "voxygen.element.ui.generic.buttons.bag.closed_press",
bag_open: "voxygen.element.ui.generic.buttons.bag.open",
bag_open_hover: "voxygen.element.ui.generic.buttons.bag.open_hover",
bag_open_press: "voxygen.element.ui.generic.buttons.bag.open_press",
map_icon: "voxygen.element.ui.generic.buttons.map",
grid_button: "voxygen.element.ui.generic.buttons.border",

View File

@ -2735,41 +2735,30 @@ impl Hud {
// Bag button and nearby icons
let ecs = client.state().ecs();
let entity = info.viewpoint_entity;
// let entity = info.viewpoint_entity;
let stats = ecs.read_storage::<comp::Stats>();
let skill_sets = ecs.read_storage::<comp::SkillSet>();
let buffs = ecs.read_storage::<comp::Buffs>();
let char_states = ecs.read_storage::<comp::CharacterState>();
let msm = ecs.read_resource::<MaterialStatManifest>();
if let (Some(player_stats), Some(skill_set)) = (stats.get(entity), skill_sets.get(entity)) {
match Buttons::new(
client,
&info,
self.show.bag,
&self.imgs,
&self.fonts,
global_state,
&self.rot_imgs,
tooltip_manager,
i18n,
player_stats,
skill_set,
self.pulse,
)
.set(self.ids.buttons, ui_widgets)
{
Some(buttons::Event::ToggleBag) => {
let state = !self.show.bag;
Self::show_bag(&mut self.slot_manager, &mut self.show, state)
},
Some(buttons::Event::ToggleSettings) => self.show.toggle_settings(global_state),
Some(buttons::Event::ToggleSocial) => self.show.toggle_social(),
Some(buttons::Event::ToggleSpell) => self.show.toggle_spell(),
Some(buttons::Event::ToggleMap) => self.show.toggle_map(),
Some(buttons::Event::ToggleCrafting) => self.show.toggle_crafting(),
None => {},
}
}
// Group Window
for event in Group::new(
&mut self.show,
@ -2924,6 +2913,7 @@ impl Hud {
self.show.diary(true);
self.show.open_skill_tree(skillgroup);
},
Some(skillbar::Event::OpenBag) => self.show.bag = !self.show.bag,
None => {},
}
}

View File

@ -4,17 +4,18 @@ use super::{
item_imgs::ItemImgs,
slots, util, BarNumbers, HudInfo, ShortcutNumbers, BLACK, CRITICAL_HP_COLOR, HP_COLOR,
LOW_HP_COLOR, POISEBAR_TICK_COLOR, POISE_COLOR, QUALITY_EPIC, QUALITY_LEGENDARY, STAMINA_COLOR,
TEXT_COLOR, UI_HIGHLIGHT_0, XP_COLOR,
TEXT_COLOR, TEXT_VELORITE, UI_HIGHLIGHT_0, XP_COLOR,
};
use crate::{
game_input::GameInput,
hud::{ComboFloater, Position, PositionSpecifier},
hud::{animation::animation_timer, ComboFloater, Position, PositionSpecifier},
ui::{
fonts::Fonts,
slot::{ContentSize, SlotMaker},
ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, TooltipManager,
Tooltipable,
},
window::KeyMouse,
GlobalState,
};
use i18n::Localization;
@ -99,6 +100,24 @@ widget_ids! {
exp_img_frame,
exp_img,
exp_lvl,
spellbook_txt_bg,
spellbook_txt,
sp_arrow,
sp_arrow_txt_bg,
sp_arrow_txt,
//Bag Button
bag_frame_bg,
bag_frame,
bag_filling,
bag_img_frame_bg,
bag_img_frame,
bag_img,
bag_space_bg,
bag_space,
bag_progress,
bag_numbers_alignment,
bag_text_bg,
bag_text,
// Combo Counter
combo_align,
combo_bg,
@ -261,6 +280,7 @@ fn slot_entries(state: &State, slot_offset: f64) -> [SlotEntry; 10] {
pub enum Event {
OpenDiary(SkillGroupKind),
OpenBag,
}
#[derive(WidgetCommon)]
@ -359,6 +379,34 @@ impl<'a> Skillbar<'a> {
}
}
fn create_new_button_with_shadow(
&self,
ui: &mut UiCell,
key_mouse: &KeyMouse,
button_identifier: widget::Id,
text_background: widget::Id,
text: widget::Id,
) {
let key_layout = &self.global_state.window.key_layout;
let key_desc = key_mouse.display_shortest(key_layout);
//Create shadow
Text::new(&key_desc)
.bottom_right_with_margins_on(button_identifier, 0.0, 0.0)
.font_size(10)
.font_id(self.fonts.cyri.conrod_id)
.color(BLACK)
.set(text_background, ui);
//Create button
Text::new(&key_desc)
.bottom_right_with_margins_on(text_background, 1.0, 1.0)
.font_size(10)
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(text, ui);
}
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;
@ -369,7 +417,7 @@ impl<'a> Skillbar<'a> {
.controls
.get_binding(GameInput::Respawn)
{
Text::new(&localized_strings.get_msg("hud-you_died"))
Text::new(&self.localized_strings.get_msg("hud-you_died"))
.middle_of(ui.window)
.font_size(self.fonts.cyri.scale(50))
.font_id(self.fonts.cyri.conrod_id)
@ -385,7 +433,7 @@ impl<'a> Skillbar<'a> {
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
.set(state.ids.death_message_2_bg, ui);
Text::new(&localized_strings.get_msg("hud-you_died"))
Text::new(&self.localized_strings.get_msg("hud-you_died"))
.bottom_left_with_margins_on(state.ids.death_message_1_bg, 2.0, 2.0)
.font_size(self.fonts.cyri.scale(50))
.font_id(self.fonts.cyri.conrod_id)
@ -533,6 +581,120 @@ impl<'a> Skillbar<'a> {
.middle_of(state.ids.bg_poise)
.set(state.ids.frame_poise, ui);
}
// Bag button and indicator
Image::new(self.imgs.selected_exp_bg)
.w_h(34.0, 38.0)
.bottom_right_with_margins_on(state.ids.slot10, 0.0, -37.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
.set(state.ids.bag_img_frame_bg, ui);
if Button::image(self.imgs.bag_frame)
.w_h(34.0, 38.0)
.middle_of(state.ids.bag_img_frame_bg)
.set(state.ids.bag_img_frame, ui)
.was_clicked()
{
return Some(Event::OpenBag);
}
let invs = self.client.inventories();
let inventory = match invs.get(self.info.viewpoint_entity) {
Some(inv) => inv,
None => return None,
};
let space_used = inventory.populated_slots();
let space_max = inventory.slots().count();
let bag_space = format!("{}/{}", space_used, space_max);
let bag_space_percentage = space_used as f64 / space_max as f64;
// bag filling indicator bar
Image::new(self.imgs.bar_content)
.w_h(1.0, 21.0 * bag_space_percentage)
.color(if bag_space_percentage < 0.6 {
Some(TEXT_VELORITE)
} else if bag_space_percentage < 1.0 {
Some(LOW_HP_COLOR)
} else {
Some(CRITICAL_HP_COLOR)
})
.graphics_for(state.ids.bag_img_frame)
.bottom_left_with_margins_on(state.ids.bag_img_frame, 14.0, 2.0)
.set(state.ids.bag_filling, ui);
// bag filling text
Rectangle::fill_with([32.0, 11.0], color::TRANSPARENT)
.bottom_left_with_margins_on(state.ids.bag_img_frame_bg, 1.0, 2.0)
.graphics_for(state.ids.bag_img_frame)
.set(state.ids.bag_numbers_alignment, ui);
Text::new(&bag_space)
.middle_of(state.ids.bag_numbers_alignment)
.font_size(if bag_space.len() < 6 { 9 } else { 8 })
.font_id(self.fonts.cyri.conrod_id)
.color(BLACK)
.graphics_for(state.ids.bag_img_frame)
.set(state.ids.bag_space_bg, ui);
Text::new(&bag_space)
.bottom_right_with_margins_on(state.ids.bag_space_bg, 1.0, 1.0)
.font_size(if bag_space.len() < 6 { 9 } else { 8 })
.font_id(self.fonts.cyri.conrod_id)
.color(if bag_space_percentage < 0.6 {
TEXT_VELORITE
} else if bag_space_percentage < 1.0 {
LOW_HP_COLOR
} else {
CRITICAL_HP_COLOR
})
.graphics_for(state.ids.bag_img_frame)
.set(state.ids.bag_space, ui);
Image::new(self.imgs.bag_ico)
.w_h(24.0, 24.0)
.graphics_for(state.ids.bag_img_frame)
.mid_bottom_with_margin_on(state.ids.bag_img_frame, 13.0)
.set(state.ids.bag_img, ui);
if let Some(bag) = &self
.global_state
.settings
.controls
.get_binding(GameInput::Bag)
{
self.create_new_button_with_shadow(
ui,
bag,
state.ids.bag_img,
state.ids.bag_text_bg,
state.ids.bag_text,
);
}
// Exp Type and Level Display
// Unspent SP indicator
let unspent_sp = self.skillset.has_available_sp();
if unspent_sp {
let arrow_ani = animation_timer(self.pulse); //Animation timer
Image::new(self.imgs.sp_indicator_arrow)
.w_h(20.0, 11.0)
.graphics_for(state.ids.exp_img_frame)
.mid_top_with_margin_on(state.ids.exp_img_frame, -12.0 + arrow_ani as f64)
.color(Some(QUALITY_LEGENDARY))
.set(state.ids.sp_arrow, ui);
Text::new(&self.localized_strings.get_msg("hud-sp_arrow_txt"))
.mid_top_with_margin_on(state.ids.sp_arrow, -18.0)
.graphics_for(state.ids.exp_img_frame)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.color(BLACK)
.set(state.ids.sp_arrow_txt_bg, ui);
Text::new(&self.localized_strings.get_msg("hud-sp_arrow_txt"))
.graphics_for(state.ids.exp_img_frame)
.bottom_right_with_margins_on(state.ids.sp_arrow_txt_bg, 1.0, 1.0)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.color(QUALITY_LEGENDARY)
.set(state.ids.sp_arrow_txt, ui);
}
if self
.global_state
@ -551,7 +713,12 @@ impl<'a> Skillbar<'a> {
let current_exp = self.skillset.available_experience(*selected_experience) as f64;
let max_exp = self.skillset.skill_point_cost(*selected_experience) as f64;
let exp_percentage = current_exp / max_exp.max(1.0);
let level = self.skillset.earned_sp(*selected_experience).to_string();
let level = self.skillset.earned_sp(*selected_experience);
let level_txt = if level > 0 {
self.skillset.earned_sp(*selected_experience).to_string()
} else {
"".to_string()
};
// Exp Bar
Image::new(self.imgs.exp_frame_bg)
@ -573,7 +740,7 @@ impl<'a> Skillbar<'a> {
Image::new(self.imgs.selected_exp_bg)
.w_h(34.0, 38.0)
.top_left_with_margins_on(state.ids.exp_frame, -39.0, 3.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.9)))
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
.set(state.ids.exp_img_frame_bg, ui);
if Button::image(self.imgs.selected_exp)
@ -585,7 +752,7 @@ impl<'a> Skillbar<'a> {
return Some(Event::OpenDiary(*selected_experience));
}
Text::new(&level)
Text::new(&level_txt)
.mid_bottom_with_margin_on(state.ids.exp_img_frame, 2.0)
.font_size(11)
.font_id(self.fonts.cyri.conrod_id)
@ -608,6 +775,60 @@ impl<'a> Skillbar<'a> {
.graphics_for(state.ids.exp_img_frame)
.mid_bottom_with_margin_on(state.ids.exp_img_frame, 13.0)
.set(state.ids.exp_img, ui);
// Show Shortcut
if let Some(spell) = &self
.global_state
.settings
.controls
.get_binding(GameInput::Spellbook)
{
self.create_new_button_with_shadow(
ui,
spell,
state.ids.exp_img,
state.ids.spellbook_txt_bg,
state.ids.spellbook_txt,
);
}
} else {
// Only show Spellbook ico
Image::new(self.imgs.selected_exp_bg)
.w_h(34.0, 38.0)
.bottom_left_with_margins_on(state.ids.slot1, 0.0, -37.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
.set(state.ids.exp_img_frame_bg, ui);
if Button::image(self.imgs.selected_exp)
.w_h(34.0, 38.0)
.middle_of(state.ids.exp_img_frame_bg)
.set(state.ids.exp_img_frame, ui)
.was_clicked()
{
return Some(Event::OpenDiary(SkillGroupKind::General));
}
Image::new(self.imgs.spellbook_ico0)
.w_h(24.0, 24.0)
.graphics_for(state.ids.exp_img_frame)
.mid_bottom_with_margin_on(state.ids.exp_img_frame, 13.0)
.set(state.ids.exp_img, ui);
// Show Shortcut
if let Some(spell) = &self
.global_state
.settings
.controls
.get_binding(GameInput::Spellbook)
{
self.create_new_button_with_shadow(
ui,
spell,
state.ids.exp_img,
state.ids.spellbook_txt_bg,
state.ids.spellbook_txt,
);
}
}
// Bar Text