mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
revamp asset system with a global singleton cache
Former-commit-id: edfc83397ed897fcec37589261c2cfae42d6ec32
This commit is contained in:
parent
b83d45c464
commit
1d5020634d
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2285,6 +2285,8 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -10,6 +10,7 @@ sphynx = { git = "https://gitlab.com/veloren/sphynx.git", features = ["serde1"]
|
||||
specs = { version = "0.14", features = ["serde", "nightly"] }
|
||||
vek = { version = "0.9", features = ["serde"] }
|
||||
dot_vox = "4.0"
|
||||
image = "0.21"
|
||||
threadpool = "1.7"
|
||||
mio = "0.6"
|
||||
mio-extras = "2.0"
|
||||
@ -19,3 +20,4 @@ bincode = "1.0"
|
||||
log = "0.4"
|
||||
rand = "0.5"
|
||||
rayon = "1.0"
|
||||
lazy_static = "1.3"
|
||||
|
146
common/src/assets/mod.rs
Normal file
146
common/src/assets/mod.rs
Normal file
@ -0,0 +1,146 @@
|
||||
use dot_vox::DotVoxData;
|
||||
use image::DynamicImage;
|
||||
use lazy_static::lazy_static;
|
||||
use std::{
|
||||
any::Any,
|
||||
collections::HashMap,
|
||||
fs::File,
|
||||
io::Read,
|
||||
sync::{Arc, PoisonError, RwLock},
|
||||
};
|
||||
use crate::figure::Segment;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Error {
|
||||
InvalidType,
|
||||
NotFound,
|
||||
Poison,
|
||||
}
|
||||
|
||||
impl From<Arc<dyn Any + 'static + Sync + Send>> for Error {
|
||||
fn from(_err: Arc<dyn Any + 'static + Sync + Send>) -> Self {
|
||||
Error::InvalidType
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(_err: std::io::Error) -> Self {
|
||||
Error::NotFound
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<PoisonError<T>> for Error {
|
||||
fn from(_err: PoisonError<T>) -> Self {
|
||||
Error::Poison
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref ASSETS: RwLock<HashMap<String, Arc<dyn Any + 'static + Sync + Send>>> =
|
||||
RwLock::new(HashMap::new());
|
||||
}
|
||||
|
||||
/// Function used to load assets
|
||||
/// Example usage:
|
||||
/// ```
|
||||
/// use image::DynamicImage;
|
||||
///
|
||||
/// let my_image = common::asset::load::<DynamicImage>("core.ui.backgrounds.city").unwrap();
|
||||
/// ```
|
||||
// TODO: consider assets that we only need in one place or that don't need to be kept in memory?
|
||||
pub fn load<A: Asset + 'static>(specifier: &str) -> Result<Arc<A>, Error> {
|
||||
Ok(ASSETS
|
||||
.write()?
|
||||
.entry(specifier.to_string())
|
||||
.or_insert(Arc::new(A::load(specifier)?))
|
||||
.clone()
|
||||
.downcast()?)
|
||||
}
|
||||
|
||||
/// Asset Trait
|
||||
pub trait Asset: Send + Sync + Sized {
|
||||
fn load(specifier: &str) -> Result<Self, Error>;
|
||||
}
|
||||
|
||||
impl Asset for DynamicImage {
|
||||
fn load(specifier: &str) -> Result<Self, Error> {
|
||||
Ok(image::load_from_memory(load_from_path(specifier)?.as_slice()).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Asset for DotVoxData {
|
||||
fn load(specifier: &str) -> Result<Self, Error> {
|
||||
Ok(dot_vox::load_bytes(load_from_path(specifier)?.as_slice()).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Asset for Segment {
|
||||
fn load(specifier: &str) -> Result<Self, Error> {
|
||||
Ok(Segment::from(dot_vox::load_bytes(load_from_path(specifier)?.as_slice()).unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: System to load file from specifiers (eg "core.ui.backgrounds.city")
|
||||
fn try_load_from_path(name: &str) -> Option<File> {
|
||||
let basepaths = [
|
||||
// if it's stupid and it works..,
|
||||
"assets".to_string(),
|
||||
"../../assets".to_string(),
|
||||
"../assets".to_string(), /* optimizations */
|
||||
[env!("CARGO_MANIFEST_DIR"), "/assets"].concat(),
|
||||
[env!("CARGO_MANIFEST_DIR"), "/../../assets"].concat(),
|
||||
[env!("CARGO_MANIFEST_DIR"), "/../assets"].concat(),
|
||||
"../../../assets".to_string(),
|
||||
[env!("CARGO_MANIFEST_DIR"), "/../../../assets"].concat(),
|
||||
];
|
||||
for bp in &basepaths {
|
||||
let filename = [bp, name].concat();
|
||||
match File::open(&filename) {
|
||||
Ok(f) => {
|
||||
debug!("loading {} succedeed", filename);
|
||||
return Some(f);
|
||||
},
|
||||
Err(e) => {
|
||||
debug!("loading {} did not work with error: {}", filename, e);
|
||||
}
|
||||
};
|
||||
};
|
||||
None
|
||||
}
|
||||
|
||||
pub fn load_from_path(name: &str) -> Result<Vec<u8>, Error> {
|
||||
match try_load_from_path(name) {
|
||||
Some(mut f) => {
|
||||
let mut content: Vec<u8> = vec!();
|
||||
f.read_to_end(&mut content);
|
||||
info!("loaded asset successful: {}", name);
|
||||
Ok(content)
|
||||
},
|
||||
None => {
|
||||
warn!("Loading asset failed, wanted to load {} but could not load it, check debug log!", name);
|
||||
Err(Error::NotFound)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/// Translation Asset
|
||||
pub struct Translations {
|
||||
pub translations: Value
|
||||
}
|
||||
impl Translations {
|
||||
pub fn get_lang(&self, lang: &str) -> &str {
|
||||
self.translations[lang].as_str().unwrap()
|
||||
}
|
||||
}
|
||||
impl Asset for Translations {
|
||||
type T=Self;
|
||||
fn load(path: &str) -> Result<Self, ()>{
|
||||
let file_out = read_from_path(path).unwrap();
|
||||
let content = from_utf8(file_out.as_slice()).unwrap();
|
||||
let value = content.parse::<Value>().unwrap();
|
||||
|
||||
Ok(Translations{translations: value})
|
||||
}
|
||||
}
|
||||
*/
|
@ -10,6 +10,7 @@ extern crate serde_derive;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
pub mod assets;
|
||||
pub mod clock;
|
||||
pub mod comp;
|
||||
pub mod figure;
|
||||
|
@ -1,189 +0,0 @@
|
||||
use super::Asset;
|
||||
|
||||
use crate::ui::{Ui, Graphic};
|
||||
|
||||
use common::figure::Segment;
|
||||
|
||||
use dot_vox::DotVoxData;
|
||||
use image::DynamicImage;
|
||||
use conrod_core::image::Id as ImgId;
|
||||
|
||||
pub trait UiId where Self: std::marker::Sized {
|
||||
fn to_ui_asset(self, ui: &mut Ui) -> ImgId;
|
||||
}
|
||||
|
||||
impl UiId for DynamicImage {
|
||||
fn to_ui_asset(self, ui: &mut Ui) -> ImgId {
|
||||
ui.new_graphic(Graphic::Image(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl UiId for DotVoxData {
|
||||
fn to_ui_asset(self, ui: &mut Ui) -> ImgId {
|
||||
ui.new_graphic(Graphic::Voxel(Segment::from(self)))
|
||||
}
|
||||
}
|
||||
|
||||
/// This macro will automatically load all specified assets, get the corresponding ImgIds and
|
||||
/// create a struct with all of them
|
||||
///
|
||||
/// Example usage:
|
||||
/// ```
|
||||
/// image_ids! {
|
||||
/// pub struct Ids {
|
||||
/// <DotVoxData>
|
||||
/// button1: "filename1.vox",
|
||||
/// button2: "filename2.vox",
|
||||
///
|
||||
/// <DynamicImage>
|
||||
/// background: "background.png",
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
macro_rules! image_ids {
|
||||
(pub struct $Ids:ident { $( <$T:ty> $( $name:ident: $file:expr ),* $(,)? )* }) => {
|
||||
pub struct $Ids {
|
||||
$($( $name: ImgId, )*)*
|
||||
}
|
||||
|
||||
impl $Ids {
|
||||
pub fn load(ui: &mut Ui) -> Result<Self, std::io::Error> {
|
||||
Ok(Self {
|
||||
$($( $name: UiId::to_ui_asset(<$T>::load($file)?, ui), )*)*
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
image_ids! {
|
||||
pub struct Ids {
|
||||
<DotVoxData>
|
||||
// Bag
|
||||
bag_contents: "element/frames/bag.vox",
|
||||
inv_grid: "element/frames/inv_grid.vox",
|
||||
inv_slot: "element/buttons/inv_slot.vox",
|
||||
|
||||
// Buttons
|
||||
settings: "element/buttons/settings.vox",
|
||||
settings_hover: "element/buttons/settings_hover.vox",
|
||||
settings_press: "element/buttons/settings_press.vox",
|
||||
|
||||
social_button: "element/buttons/social.vox",
|
||||
social_hover: "element/buttons/social_hover.vox",
|
||||
social_press: "element/buttons/social_press.vox",
|
||||
|
||||
map_button: "element/buttons/map.vox",
|
||||
map_hover: "element/buttons/map_hover.vox",
|
||||
map_press: "element/buttons/map_press.vox",
|
||||
|
||||
spellbook_button: "element/buttons/spellbook.vox",
|
||||
spellbook_hover: "element/buttons/spellbook_hover.vox",
|
||||
spellbook_press: "element/buttons/spellbook_press.vox",
|
||||
|
||||
character_button: "element/buttons/character.vox",
|
||||
character_hover: "element/buttons/character_hover.vox",
|
||||
character_press: "element/buttons/character_press.vox",
|
||||
|
||||
qlog_button: "element/buttons/qlog.vox",
|
||||
qlog_hover: "element/buttons/qlog_hover.vox",
|
||||
qlog_press: "element/buttons/qlog_press.vox",
|
||||
|
||||
close_button: "element/buttons/x.vox",
|
||||
close_button_hover: "element/buttons/x_hover.vox",
|
||||
close_button_press: "element/buttons/x_press.vox",
|
||||
|
||||
// Esc menu
|
||||
fireplace: "element/misc_bg/fireplace.vox",
|
||||
button_dark: "element/buttons/button_dark.vox",
|
||||
|
||||
// Minimap
|
||||
mmap_frame: "element/frames/mmap.vox",
|
||||
window_frame: "element/frames/window2.vox",
|
||||
map_frame_l: "element/frames/map_l.vox",
|
||||
map_frame_r: "element/frames/map_r.vox",
|
||||
|
||||
<DynamicImage>
|
||||
// Bag
|
||||
bag: "element/buttons/bag/closed.png",
|
||||
bag_hover: "element/buttons/bag/closed_hover.png",
|
||||
bag_press: "element/buttons/bag/closed_press.png",
|
||||
bag_open: "element/buttons/bag/open.png",
|
||||
bag_open_hover: "element/buttons/bag/open_hover.png",
|
||||
bag_open_press: "element/buttons/bag/open_press.png",
|
||||
|
||||
// Buttons
|
||||
mmap_button: "element/buttons/border.png",
|
||||
mmap_button_hover: "element/buttons/border_mo.png",
|
||||
mmap_button_press: "element/buttons/border_press.png",
|
||||
mmap_button_open: "element/buttons/border_pressed.png",
|
||||
|
||||
// Esc-Menu
|
||||
esc_bg: "element/frames/menu.png",
|
||||
button_dark_hover: "element/buttons/button_dark_hover.png",
|
||||
button_dark_press: "element/buttons/button_dark_press.png",
|
||||
|
||||
// MiniMap
|
||||
mmap_frame_bg: "element/misc_bg/mmap_bg.png",
|
||||
|
||||
// Skillbar Module
|
||||
sb_grid: "element/skill_bar/sbar_grid.png",
|
||||
sb_grid_bg: "element/skill_bar/sbar_grid_bg.png",
|
||||
l_click: "element/skill_bar/l.png",
|
||||
r_click: "element/skill_bar/r.png",
|
||||
mana_bar: "element/skill_bar/mana_bar.png",
|
||||
health_bar: "element/skill_bar/health_bar.png",
|
||||
xp_bar: "element/skill_bar/xp_bar.png",
|
||||
|
||||
// Missing: Buff Frame Animation (.gif ?!) (we could do animation in ui.maintain(), or in shader?)
|
||||
window_frame_2: "element/frames/window_2.png",
|
||||
|
||||
// Settings Window
|
||||
settings_bg: "element/frames/settings.png",
|
||||
settings_icon: "element/icons/settings.png",
|
||||
settings_button_mo: "element/buttons/blue_mo.png",
|
||||
check: "element/buttons/check/no.png",
|
||||
check_mo: "element/buttons/check/no_mo.png",
|
||||
check_press: "element/buttons/check/press.png",
|
||||
check_checked: "element/buttons/check/yes.png",
|
||||
check_checked_mo: "element/buttons/check/yes_mo.png",
|
||||
slider: "element/slider/track.png",
|
||||
slider_indicator: "element/slider/indicator.png",
|
||||
//button_blank: ui.new_graphic(ui::Graphic::Blank),
|
||||
button_blue_mo: "element/buttons/blue_mo.png",
|
||||
button_blue_press: "element/buttons/blue_press.png",
|
||||
|
||||
// Window BG
|
||||
window_bg: "element/misc_bg/window_bg.png",
|
||||
|
||||
// Social Window
|
||||
social_bg: "element/misc_bg/small_bg.png",
|
||||
social_icon: "element/icons/social.png",
|
||||
|
||||
// Map Window
|
||||
map_bg: "element/misc_bg/small_bg.png",
|
||||
map_icon: "element/icons/map.png",
|
||||
|
||||
// Spell Book Window
|
||||
spellbook_bg: "element/misc_bg/small_bg.png",
|
||||
spellbook_icon: "element/icons/spellbook.png",
|
||||
|
||||
// Char Window
|
||||
charwindow: "element/misc_bg/charwindow.png",
|
||||
charwindow_icon: "element/icons/charwindow.png",
|
||||
charwindow_tab_bg: "element/frames/tab.png",
|
||||
charwindow_tab: "element/buttons/tab.png",
|
||||
charwindow_expbar: "element/misc_bg/small_bg.png",
|
||||
progress_frame: "element/frames/progress_bar.png",
|
||||
progress: "element/misc_bg/progress.png",
|
||||
|
||||
// Quest-Log Window
|
||||
questlog_bg: "element/misc_bg/small_bg.png",
|
||||
questlog_icon: "element/icons/questlog.png",
|
||||
|
||||
// Chat-Arrows
|
||||
chat_arrow: "element/buttons/arrow/chat_arrow.png",
|
||||
chat_arrow_mo: "element/buttons/arrow/chat_arrow_mo.png",
|
||||
chat_arrow_press: "element/buttons/arrow/chat_arrow_press.png",
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
pub mod ids;
|
||||
|
||||
use conrod_core::widget::image::Image;
|
||||
|
||||
use crate::ui::Ui;
|
||||
use crate::ui::Graphic;
|
||||
|
||||
use dot_vox::DotVoxData;
|
||||
use image::DynamicImage;
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::fs::File;
|
||||
|
||||
fn read_from_path(path: &str) -> Result<Vec<u8>, std::io::Error> {
|
||||
let path_slash = path.replace(".", "/");
|
||||
let path_slash_toml = [env!("CARGO_MANIFEST_DIR"), &path_slash, ".toml"].concat();
|
||||
println!("{}", path_slash_toml);
|
||||
|
||||
let mut content = Vec::new();
|
||||
File::open(path_slash_toml)?.read_to_end(&mut content);
|
||||
Ok(content)
|
||||
}
|
||||
|
||||
pub trait Asset where Self: std::marker::Sized {
|
||||
fn load(path: &str) -> Result<Self, std::io::Error>;
|
||||
}
|
||||
|
||||
impl Asset for DynamicImage {
|
||||
fn load(path: &str) -> Result<Self, std::io::Error> {
|
||||
let image = image::load_from_memory(
|
||||
&read_from_path(path)?
|
||||
).unwrap();
|
||||
|
||||
Ok(image)
|
||||
}
|
||||
}
|
||||
|
||||
impl Asset for DotVoxData {
|
||||
fn load(path: &str) -> Result<Self, std::io::Error> {
|
||||
let dot_vox = dot_vox::load_bytes(
|
||||
&read_from_path(path)?
|
||||
).unwrap();
|
||||
|
||||
Ok(dot_vox)
|
||||
}
|
||||
}
|
||||
|
@ -6,21 +6,17 @@ use self::character_window::CharacterWindow;
|
||||
use crate::{
|
||||
render::Renderer,
|
||||
settings::{ControlSettings, Settings},
|
||||
ui::{self, ScaleMode, ToggleButton, Ui},
|
||||
ui::{ScaleMode, ToggleButton, Ui, Graphic},
|
||||
window::{Event as WinEvent, Key, Window},
|
||||
GlobalState,
|
||||
};
|
||||
use common::{
|
||||
assets,
|
||||
figure::Segment};
|
||||
|
||||
use conrod_core::{
|
||||
color,
|
||||
image::Id as ImgId,
|
||||
text::font::Id as FontId,
|
||||
widget::{self,Style, Button, Image, Rectangle, Scrollbar, Text},
|
||||
WidgetStyle, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
|
||||
};
|
||||
use common::assets;
|
||||
|
||||
// TODO: Use styles?
|
||||
const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
||||
@ -210,6 +206,138 @@ widget_ids! {
|
||||
}
|
||||
}
|
||||
|
||||
image_ids! {
|
||||
pub(self) struct<common::figure::Segment> Voxs {
|
||||
// Bag
|
||||
bag_contents: "/voxygen/element/frames/bag.vox",
|
||||
inv_grid: "/voxygen/element/frames/inv_grid.vox",
|
||||
inv_slot: "/voxygen/element/buttons/inv_slot.vox",
|
||||
|
||||
// Buttons
|
||||
settings: "/voxygen/element/buttons/settings.vox",
|
||||
settings_hover: "/voxygen/element/buttons/settings_hover.vox",
|
||||
settings_press: "/voxygen/element/buttons/settings_press.vox",
|
||||
|
||||
social_button: "/voxygen/element/buttons/social.vox",
|
||||
social_hover: "/voxygen/element/buttons/social_hover.vox",
|
||||
social_press: "/voxygen/element/buttons/social_press.vox",
|
||||
|
||||
map_button: "/voxygen/element/buttons/map.vox",
|
||||
map_hover: "/voxygen/element/buttons/map_hover.vox",
|
||||
map_press: "/voxygen/element/buttons/map_press.vox",
|
||||
|
||||
spellbook_button: "/voxygen/element/buttons/spellbook.vox",
|
||||
spellbook_hover: "/voxygen/element/buttons/spellbook_hover.vox",
|
||||
spellbook_press: "/voxygen/element/buttons/spellbook_press.vox",
|
||||
|
||||
character_button: "/voxygen/element/buttons/character.vox",
|
||||
character_hover: "/voxygen/element/buttons/character_hover.vox",
|
||||
character_press: "/voxygen/element/buttons/character_press.vox",
|
||||
|
||||
qlog_button: "/voxygen/element/buttons/qlog.vox",
|
||||
qlog_hover: "/voxygen/element/buttons/qlog_hover.vox",
|
||||
qlog_press: "/voxygen/element/buttons/qlog_press.vox",
|
||||
|
||||
close_button: "/voxygen/element/buttons/x.vox",
|
||||
close_button_hover: "/voxygen/element/buttons/x_hover.vox",
|
||||
close_button_press: "/voxygen/element/buttons/x_press.vox",
|
||||
|
||||
// Esc menu
|
||||
fireplace: "/voxygen/element/misc_bg/fireplace.vox",
|
||||
button_dark: "/voxygen/element/buttons/button_dark.vox",
|
||||
|
||||
// Minimap
|
||||
mmap_frame: "/voxygen/element/frames/mmap.vox",
|
||||
window_frame: "/voxygen/element/frames/window2.vox",
|
||||
map_frame_l: "/voxygen/element/frames/map_l.vox",
|
||||
map_frame_r: "/voxygen/element/frames/map_r.vox",
|
||||
}
|
||||
|
||||
pub(self) struct<image::DynamicImage> Imgs {
|
||||
// Bag
|
||||
bag: "/voxygen/element/buttons/bag/closed.png",
|
||||
bag_hover: "/voxygen/element/buttons/bag/closed_hover.png",
|
||||
bag_press: "/voxygen/element/buttons/bag/closed_press.png",
|
||||
bag_open: "/voxygen/element/buttons/bag/open.png",
|
||||
bag_open_hover: "/voxygen/element/buttons/bag/open_hover.png",
|
||||
bag_open_press: "/voxygen/element/buttons/bag/open_press.png",
|
||||
|
||||
// Buttons
|
||||
mmap_button: "/voxygen/element/buttons/border.png",
|
||||
mmap_button_hover: "/voxygen/element/buttons/border_mo.png",
|
||||
mmap_button_press: "/voxygen/element/buttons/border_press.png",
|
||||
mmap_button_open: "/voxygen/element/buttons/border_pressed.png",
|
||||
|
||||
// Esc-Menu
|
||||
esc_bg: "/voxygen/element/frames/menu.png",
|
||||
button_dark_hover: "/voxygen/element/buttons/button_dark_hover.png",
|
||||
button_dark_press: "/voxygen/element/buttons/button_dark_press.png",
|
||||
|
||||
// MiniMap
|
||||
mmap_frame_bg: "/voxygen/element/misc_bg/mmap_bg.png",
|
||||
|
||||
// Skillbar Module
|
||||
sb_grid: "/voxygen/element/skill_bar/sbar_grid.png",
|
||||
sb_grid_bg: "/voxygen/element/skill_bar/sbar_grid_bg.png",
|
||||
l_click: "/voxygen/element/skill_bar/l.png",
|
||||
r_click: "/voxygen/element/skill_bar/r.png",
|
||||
mana_bar: "/voxygen/element/skill_bar/mana_bar.png",
|
||||
health_bar: "/voxygen/element/skill_bar/health_bar.png",
|
||||
xp_bar: "/voxygen/element/skill_bar/xp_bar.png",
|
||||
|
||||
// Missing: Buff Frame Animation (.gif ?!) (we could do animation in ui.maintain(), or in shader?)
|
||||
window_frame_2: "/voxygen/element/frames/window_2.png",
|
||||
|
||||
// Settings Window
|
||||
settings_bg: "/voxygen/element/frames/settings.png",
|
||||
settings_icon: "/voxygen/element/icons/settings.png",
|
||||
settings_button_mo: "/voxygen/element/buttons/blue_mo.png",
|
||||
check: "/voxygen/element/buttons/check/no.png",
|
||||
check_mo: "/voxygen/element/buttons/check/no_mo.png",
|
||||
check_press: "/voxygen/element/buttons/check/press.png",
|
||||
check_checked: "/voxygen/element/buttons/check/yes.png",
|
||||
check_checked_mo: "/voxygen/element/buttons/check/yes_mo.png",
|
||||
slider: "/voxygen/element/slider/track.png",
|
||||
slider_indicator: "/voxygen/element/slider/indicator.png",
|
||||
//button_blank: ui.new_graphic(ui::Graphic::Blank),
|
||||
button_blue_mo: "/voxygen/element/buttons/blue_mo.png",
|
||||
button_blue_press: "/voxygen/element/buttons/blue_press.png",
|
||||
|
||||
// Window BG
|
||||
window_bg: "/voxygen/element/misc_bg/window_bg.png",
|
||||
|
||||
// Social Window
|
||||
social_bg: "/voxygen/element/misc_bg/small_bg.png",
|
||||
social_icon: "/voxygen/element/icons/social.png",
|
||||
|
||||
// Map Window
|
||||
map_bg: "/voxygen/element/misc_bg/small_bg.png",
|
||||
map_icon: "/voxygen/element/icons/map.png",
|
||||
|
||||
// Spell Book Window
|
||||
spellbook_bg: "/voxygen/element/misc_bg/small_bg.png",
|
||||
spellbook_icon: "/voxygen/element/icons/spellbook.png",
|
||||
|
||||
// Char Window
|
||||
charwindow: "/voxygen/element/misc_bg/charwindow.png",
|
||||
charwindow_icon: "/voxygen/element/icons/charwindow.png",
|
||||
charwindow_tab_bg: "/voxygen/element/frames/tab.png",
|
||||
charwindow_tab: "/voxygen/element/buttons/tab.png",
|
||||
charwindow_expbar: "/voxygen/element/misc_bg/small_bg.png",
|
||||
progress_frame: "/voxygen/element/frames/progress_bar.png",
|
||||
progress: "/voxygen/element/misc_bg/progress.png",
|
||||
|
||||
// Quest-Log Window
|
||||
questlog_bg: "/voxygen/element/misc_bg/small_bg.png",
|
||||
questlog_icon: "/voxygen/element/icons/questlog.png",
|
||||
|
||||
// Chat-Arrows
|
||||
chat_arrow: "/voxygen/element/buttons/arrow/chat_arrow.png",
|
||||
chat_arrow_mo: "/voxygen/element/buttons/arrow/chat_arrow_mo.png",
|
||||
chat_arrow_press: "/voxygen/element/buttons/arrow/chat_arrow_press.png",
|
||||
}
|
||||
}
|
||||
|
||||
enum SettingsTab {
|
||||
Interface,
|
||||
Video,
|
||||
@ -244,6 +372,8 @@ pub struct Hud {
|
||||
ui: Ui,
|
||||
ids: Ids,
|
||||
imgs: Imgs,
|
||||
voxs: Voxs,
|
||||
blank_img: conrod_core::image::Id,
|
||||
chat: chat::Chat,
|
||||
font_metamorph: FontId,
|
||||
font_opensans: FontId,
|
||||
@ -277,13 +407,18 @@ impl Hud {
|
||||
// Generate ids
|
||||
let ids = Ids::new(ui.id_generator());
|
||||
// Load images
|
||||
let imgs = Imgs::new(&mut ui, window.renderer_mut());
|
||||
let imgs = Imgs::load(&mut ui).unwrap();
|
||||
// Load vox files
|
||||
let voxs = Voxs::load(&mut ui).unwrap();
|
||||
// Blank graphic
|
||||
let blank_img = ui.new_graphic(Graphic::Blank);
|
||||
// Load fonts
|
||||
let load_font = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/font", filename].concat();
|
||||
// TODO: use Asset trait to load font
|
||||
ui.new_font(
|
||||
conrod_core::text::Font::from_bytes(
|
||||
assets::load(fullpath.as_str()).expect("Error loading file"),
|
||||
assets::load_from_path(fullpath.as_str()).expect("Error loading file")
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
@ -296,6 +431,8 @@ impl Hud {
|
||||
Self {
|
||||
ui,
|
||||
imgs,
|
||||
voxs,
|
||||
blank_img,
|
||||
ids,
|
||||
chat,
|
||||
settings_tab: SettingsTab::Interface,
|
||||
@ -387,10 +524,10 @@ impl Hud {
|
||||
.font_size(18)
|
||||
.set(self.ids.help, ui_widgets);
|
||||
// X-button
|
||||
if Button::image(self.imgs.close_button)
|
||||
if Button::image(self.voxs.close_button)
|
||||
.w_h(100.0 * 0.2, 100.0 * 0.2)
|
||||
.hover_image(self.imgs.close_button_hover)
|
||||
.press_image(self.imgs.close_button_press)
|
||||
.hover_image(self.voxs.close_button_hover)
|
||||
.press_image(self.voxs.close_button_press)
|
||||
.top_right_with_margins_on(self.ids.help_bg, 8.0, 3.0)
|
||||
.set(self.ids.button_help2, ui_widgets)
|
||||
.was_clicked()
|
||||
@ -451,7 +588,7 @@ impl Hud {
|
||||
// Buttons at Bag
|
||||
|
||||
// 0 Settings
|
||||
if Button::image(self.imgs.settings)
|
||||
if Button::image(self.voxs.settings)
|
||||
.w_h(29.0, 25.0)
|
||||
.bottom_right_with_margins_on(ui_widgets.window, 5.0, 57.0)
|
||||
.hover_image(self.imgs.settings_hover)
|
||||
@ -474,7 +611,7 @@ impl Hud {
|
||||
};
|
||||
|
||||
// 2 Map
|
||||
if Button::image(self.imgs.map_button)
|
||||
if Button::image(self.voxs.map_button)
|
||||
.w_h(22.0, 25.0)
|
||||
.left_from(self.ids.social_button, 10.0)
|
||||
.hover_image(self.imgs.map_hover)
|
||||
@ -495,19 +632,19 @@ impl Hud {
|
||||
// Other Windows can only be accessed, when Settings are closed.
|
||||
// Opening Settings will close all other Windows including the Bag.
|
||||
// Opening the Map won't close the windows displayed before.
|
||||
Image::new(self.imgs.social_button)
|
||||
Image::new(self.voxs.social_button)
|
||||
.w_h(25.0, 25.0)
|
||||
.left_from(self.ids.settings_button, 10.0)
|
||||
.set(self.ids.social_button_bg, ui_widgets);
|
||||
Image::new(self.imgs.spellbook_button)
|
||||
Image::new(self.voxs.spellbook_button)
|
||||
.w_h(28.0, 25.0)
|
||||
.left_from(self.ids.map_button, 10.0)
|
||||
.set(self.ids.spellbook_button_bg, ui_widgets);
|
||||
Image::new(self.imgs.character_button)
|
||||
Image::new(self.voxs.character_button)
|
||||
.w_h(27.0, 25.0)
|
||||
.left_from(self.ids.spellbook_button, 10.0)
|
||||
.set(self.ids.character_button_bg, ui_widgets);
|
||||
Image::new(self.imgs.qlog_button)
|
||||
Image::new(self.voxs.qlog_button)
|
||||
.w_h(23.0, 25.0)
|
||||
.left_from(self.ids.character_button, 10.0)
|
||||
.set(self.ids.qlog_button_bg, ui_widgets);
|
||||
@ -518,7 +655,7 @@ impl Hud {
|
||||
} && self.map_open == false
|
||||
{
|
||||
// 1 Social
|
||||
if Button::image(self.imgs.social_button)
|
||||
if Button::image(self.voxs.social_button)
|
||||
.w_h(25.0, 25.0)
|
||||
.left_from(self.ids.settings_button, 10.0)
|
||||
.hover_image(self.imgs.social_hover)
|
||||
@ -544,7 +681,7 @@ impl Hud {
|
||||
}
|
||||
|
||||
// 3 Spellbook
|
||||
if Button::image(self.imgs.spellbook_button)
|
||||
if Button::image(self.voxs.spellbook_button)
|
||||
.w_h(28.0, 25.0)
|
||||
.left_from(self.ids.map_button, 10.0)
|
||||
.hover_image(self.imgs.spellbook_hover)
|
||||
@ -570,7 +707,7 @@ impl Hud {
|
||||
}
|
||||
|
||||
// 4 Char-Window
|
||||
if Button::image(self.imgs.character_button)
|
||||
if Button::image(self.voxs.character_button)
|
||||
.w_h(27.0, 25.0)
|
||||
.left_from(self.ids.spellbook_button, 10.0)
|
||||
.hover_image(self.imgs.character_hover)
|
||||
@ -1182,12 +1319,12 @@ impl Hud {
|
||||
Small::Social => {
|
||||
//Frame
|
||||
if char_window_open {
|
||||
Image::new(self.imgs.window_frame)
|
||||
Image::new(self.voxs.window_frame)
|
||||
.right_from(self.ids.charwindow_frame, 20.0)
|
||||
.w_h(107.0 * 4.0, 125.0 * 4.0)
|
||||
.set(self.ids.social_frame, ui_widgets);
|
||||
} else {
|
||||
Image::new(self.imgs.window_frame)
|
||||
Image::new(self.voxs.window_frame)
|
||||
.top_left_with_margins_on(ui_widgets.window, 200.0, 10.0)
|
||||
.w_h(107.0 * 4.0, 125.0 * 4.0)
|
||||
.set(self.ids.social_frame, ui_widgets);
|
||||
@ -1232,7 +1369,7 @@ impl Hud {
|
||||
Small::Spellbook => {
|
||||
// Frame
|
||||
if char_window_open {
|
||||
Image::new(self.imgs.window_frame)
|
||||
Image::new(self.voxs.window_frame)
|
||||
.right_from(self.ids.charwindow_frame, 20.0)
|
||||
.w_h(107.0 * 4.0, 125.0 * 4.0)
|
||||
.set(self.ids.spellbook_frame, ui_widgets);
|
||||
@ -1281,7 +1418,7 @@ impl Hud {
|
||||
Small::Questlog => {
|
||||
// Frame
|
||||
if char_window_open {
|
||||
Image::new(self.imgs.window_frame)
|
||||
Image::new(self.voxs.window_frame)
|
||||
.right_from(self.ids.charwindow_frame, 20.0)
|
||||
.w_h(107.0 * 4.0, 125.0 * 4.0)
|
||||
.set(self.ids.questlog_frame, ui_widgets);
|
||||
@ -1342,7 +1479,7 @@ impl Hud {
|
||||
.scroll_kids_vertically()
|
||||
.set(self.ids.map_bg, ui_widgets);
|
||||
// Frame
|
||||
Image::new(self.imgs.map_frame_l)
|
||||
Image::new(self.voxs.map_frame_l)
|
||||
.top_left_with_margins_on(self.ids.map_bg, 0.0, 0.0)
|
||||
.w_h(412.0, 488.0)
|
||||
.set(self.ids.map_frame_l, ui_widgets);
|
||||
@ -1392,7 +1529,7 @@ impl Hud {
|
||||
.middle_of(ui_widgets.window)
|
||||
.set(self.ids.esc_bg, ui_widgets);
|
||||
|
||||
Image::new(self.imgs.fireplace)
|
||||
Image::new(self.voxs.fireplace)
|
||||
.w_h(180.0, 60.0)
|
||||
.mid_top_with_margin_on(self.ids.esc_bg, 50.0)
|
||||
.set(self.ids.fireplace, ui_widgets);
|
||||
|
@ -1,7 +1,8 @@
|
||||
#![feature(drain_filter)]
|
||||
#![recursion_limit = "2048"]
|
||||
|
||||
pub mod assets;
|
||||
#[macro_use]
|
||||
pub mod ui;
|
||||
pub mod anim;
|
||||
pub mod error;
|
||||
pub mod hud;
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::{
|
||||
assets,
|
||||
render::Renderer,
|
||||
ui::{self, ScaleMode, Ui},
|
||||
window::Window,
|
||||
@ -232,26 +231,18 @@ struct Imgs {
|
||||
icon_border_pressed: ImgId,
|
||||
}
|
||||
impl Imgs {
|
||||
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
|
||||
fn new(ui: &mut Ui) -> Imgs {
|
||||
let load_img = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/", filename].concat();
|
||||
let image = image::load_from_memory(
|
||||
assets::load(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
.as_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
ui.new_graphic(ui::Graphic::Image(image))
|
||||
let image = assets::load::<image::DynamicImage>(fullpath.as_str())
|
||||
.expect("Error loading file");
|
||||
ui.new_graphic(image.into())
|
||||
};
|
||||
let load_vox = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/", filename].concat();
|
||||
let dot_vox = dot_vox::load_bytes(
|
||||
assets::load(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
.as_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
ui.new_graphic(ui::Graphic::Voxel(Segment::from(dot_vox)))
|
||||
let segment = assets::load::<common::figure::Segment>(fullpath.as_str())
|
||||
.expect("Error loading file");
|
||||
ui.new_graphic(segment.into())
|
||||
};
|
||||
Imgs {
|
||||
v_logo: load_vox("element/v_logo.vox", ui),
|
||||
@ -368,16 +359,14 @@ impl CharSelectionUi {
|
||||
// Generate ids
|
||||
let ids = Ids::new(ui.id_generator());
|
||||
// Load images
|
||||
let imgs = Imgs::new(&mut ui, window.renderer_mut());
|
||||
let imgs = Imgs::new(&mut ui);
|
||||
// Load fonts
|
||||
let load_font = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/font", filename].concat();
|
||||
ui.new_font(
|
||||
conrod_core::text::Font::from_bytes(
|
||||
assets::load(fullpath.as_str()).expect("Error loading file"),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
ui.new_font(conrod_core::text::Font::from_bytes(
|
||||
assets::load_from_path(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
).unwrap())
|
||||
};
|
||||
let font_opensans = load_font("/OpenSans-Regular.ttf", &mut ui);
|
||||
let font_metamorph = load_font("/Metamorphous-Regular.ttf", &mut ui);
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::{
|
||||
assets,
|
||||
render::Renderer,
|
||||
ui::{self, ScaleMode, Ui},
|
||||
window::Window,
|
||||
GlobalState, DEFAULT_PUBLIC_SERVER,
|
||||
};
|
||||
use common::figure::Segment;
|
||||
use common::{
|
||||
assets,
|
||||
figure::Segment,
|
||||
};
|
||||
use conrod_core::{
|
||||
color,
|
||||
color::TRANSPARENT,
|
||||
@ -64,26 +66,18 @@ struct Imgs {
|
||||
button_press: ImgId,
|
||||
}
|
||||
impl Imgs {
|
||||
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
|
||||
fn new(ui: &mut Ui) -> Imgs {
|
||||
let load_img = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/", filename].concat();
|
||||
let image = image::load_from_memory(
|
||||
assets::load(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
.as_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
ui.new_graphic(ui::Graphic::Image(image))
|
||||
let image = assets::load::<image::DynamicImage>(fullpath.as_str())
|
||||
.expect("Error loading file");
|
||||
ui.new_graphic(image.into())
|
||||
};
|
||||
let load_vox = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/", filename].concat();
|
||||
let dot_vox = dot_vox::load_bytes(
|
||||
assets::load(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
.as_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
ui.new_graphic(ui::Graphic::Voxel(Segment::from(dot_vox)))
|
||||
let segment = assets::load::<common::figure::Segment>(fullpath.as_str())
|
||||
.expect("Error loading file");
|
||||
ui.new_graphic(segment.into())
|
||||
};
|
||||
Imgs {
|
||||
bg: load_img("background/bg_main.png", ui),
|
||||
@ -132,13 +126,13 @@ impl MainMenuUi {
|
||||
// Generate ids
|
||||
let ids = Ids::new(ui.id_generator());
|
||||
// Load images
|
||||
let imgs = Imgs::new(&mut ui, window.renderer_mut());
|
||||
let imgs = Imgs::new(&mut ui);
|
||||
// Load fonts
|
||||
let load_font = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/font", filename].concat();
|
||||
ui.new_font(
|
||||
conrod_core::text::Font::from_bytes(
|
||||
assets::load(fullpath.as_str()).expect("Error loading file"),
|
||||
assets::load_from_path(fullpath.as_str()).expect("Error loading file")
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
|
@ -100,15 +100,9 @@ impl FigureCache {
|
||||
|
||||
fn load_mesh(filename: &'static str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
|
||||
let fullpath: String = ["/voxygen/voxel/", filename].concat();
|
||||
Segment::from(
|
||||
dot_vox::load_bytes(
|
||||
assets::load(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
.as_slice(),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.generate_mesh(position)
|
||||
assets::load::<Segment>(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
.generate_mesh(position)
|
||||
}
|
||||
|
||||
fn load_head(head: Head) -> Mesh<FigurePipeline> {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::sync::Arc;
|
||||
use common::figure::Segment;
|
||||
use fnv::FnvHashMap;
|
||||
use guillotiere::{size2, Allocation, AtlasAllocator};
|
||||
@ -5,10 +6,22 @@ use image::DynamicImage;
|
||||
use vek::*;
|
||||
|
||||
pub enum Graphic {
|
||||
Image(DynamicImage),
|
||||
Voxel(Segment),
|
||||
Image(Arc<DynamicImage>),
|
||||
Voxel(Arc<Segment>),
|
||||
Blank,
|
||||
}
|
||||
|
||||
impl From<Arc<DynamicImage>> for Graphic {
|
||||
fn from(image: Arc<DynamicImage>) -> Self {
|
||||
Graphic::Image(image)
|
||||
}
|
||||
}
|
||||
impl From<Arc<Segment>> for Graphic {
|
||||
fn from(vox: Arc<Segment>) -> Self {
|
||||
Graphic::Voxel(vox)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
|
||||
pub struct Id(u32);
|
||||
|
||||
@ -92,8 +105,8 @@ impl GraphicCache {
|
||||
.pixels()
|
||||
.map(|p| p.data)
|
||||
.collect::<Vec<[u8; 4]>>(),
|
||||
Graphic::Voxel(segment) => {
|
||||
super::renderer::draw_vox(&segment, aabr.size().into())
|
||||
Graphic::Voxel(vox) => {
|
||||
super::renderer::draw_vox(&vox, aabr.size().into())
|
||||
}
|
||||
Graphic::Blank => return None,
|
||||
};
|
||||
|
34
voxygen/src/ui/img_ids.rs
Normal file
34
voxygen/src/ui/img_ids.rs
Normal file
@ -0,0 +1,34 @@
|
||||
/// This macro will automatically load all specified assets, get the corresponding ImgIds and
|
||||
/// create a struct with all of them
|
||||
///
|
||||
/// Example usage:
|
||||
/// ```
|
||||
/// image_ids! {
|
||||
/// struct<DotVoxData> Voxs {
|
||||
/// button1: "filename1.vox",
|
||||
/// button2: "filename2.vox",
|
||||
/// }
|
||||
/// struct<DynamicImage> Imgs {
|
||||
/// background: "background.png",
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
// TODO: will this work with shorter name paths? eg not rate::ui::Graphic::
|
||||
#[macro_export]
|
||||
macro_rules! image_ids {
|
||||
($($v:vis struct<$T:ty> $Ids:ident { $( $name:ident: $specifier:expr ), *$(,)? } )*) => {
|
||||
$(
|
||||
$v struct $Ids {
|
||||
$( $name: conrod_core::image::Id, )*
|
||||
}
|
||||
|
||||
impl $Ids {
|
||||
pub fn load(ui: &mut Ui) -> Result<Self, common::assets::Error> {
|
||||
Ok(Self {
|
||||
$( $name: ui.new_graphic(common::assets::load::<$T>($specifier)?.into()), )*
|
||||
})
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
mod graphic;
|
||||
mod util;
|
||||
mod widgets;
|
||||
#[macro_use]
|
||||
mod img_ids;
|
||||
|
||||
pub use graphic::Graphic;
|
||||
pub(self) use util::{linear_to_srgb, srgb_to_linear};
|
||||
|
Loading…
Reference in New Issue
Block a user