FileOrBuiltIn asset paths, theming support
This commit is contained in:
@@ -5,16 +5,16 @@ use std::path::{Component, Path, PathBuf};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AssetPath<'a> {
|
||||
WguiInternal(&'a str), // tied to internal wgui AssetProvider. Used internally
|
||||
BuiltIn(&'a str), // tied to user AssetProvider
|
||||
Filesystem(&'a str), // tied to filesystem path
|
||||
WguiInternal(&'a str), // tied to internal wgui AssetProvider. Used internally
|
||||
BuiltIn(&'a str), // tied to user AssetProvider
|
||||
FileOrBuiltIn(&'a str), // attempts to load from a path relative to asset_folder, falls back to BuiltIn
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum AssetPathOwned {
|
||||
WguiInternal(PathBuf),
|
||||
BuiltIn(PathBuf),
|
||||
Filesystem(PathBuf),
|
||||
FileOrBuiltIn(PathBuf),
|
||||
}
|
||||
|
||||
impl AssetPath<'_> {
|
||||
@@ -22,7 +22,7 @@ impl AssetPath<'_> {
|
||||
match &self {
|
||||
AssetPath::WguiInternal(path) => path,
|
||||
AssetPath::BuiltIn(path) => path,
|
||||
AssetPath::Filesystem(path) => path,
|
||||
AssetPath::FileOrBuiltIn(path) => path,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ impl AssetPath<'_> {
|
||||
match self {
|
||||
AssetPath::WguiInternal(path) => AssetPathOwned::WguiInternal(PathBuf::from(path)),
|
||||
AssetPath::BuiltIn(path) => AssetPathOwned::BuiltIn(PathBuf::from(path)),
|
||||
AssetPath::Filesystem(path) => AssetPathOwned::Filesystem(PathBuf::from(path)),
|
||||
AssetPath::FileOrBuiltIn(path) => AssetPathOwned::FileOrBuiltIn(PathBuf::from(path)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ impl AssetPathOwned {
|
||||
match self {
|
||||
AssetPathOwned::WguiInternal(buf) => AssetPath::WguiInternal(buf.to_str().unwrap()),
|
||||
AssetPathOwned::BuiltIn(buf) => AssetPath::BuiltIn(buf.to_str().unwrap()),
|
||||
AssetPathOwned::Filesystem(buf) => AssetPath::Filesystem(buf.to_str().unwrap()),
|
||||
AssetPathOwned::FileOrBuiltIn(buf) => AssetPath::FileOrBuiltIn(buf.to_str().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ impl AssetPathOwned {
|
||||
match self {
|
||||
AssetPathOwned::WguiInternal(buf) => buf,
|
||||
AssetPathOwned::BuiltIn(buf) => buf,
|
||||
AssetPathOwned::Filesystem(buf) => buf,
|
||||
AssetPathOwned::FileOrBuiltIn(buf) => buf,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ impl AssetPathOwned {
|
||||
match self {
|
||||
AssetPathOwned::WguiInternal(_) => AssetPathOwned::WguiInternal(new_path),
|
||||
AssetPathOwned::BuiltIn(_) => AssetPathOwned::BuiltIn(new_path),
|
||||
AssetPathOwned::Filesystem(_) => AssetPathOwned::Filesystem(new_path),
|
||||
AssetPathOwned::FileOrBuiltIn(_) => AssetPathOwned::FileOrBuiltIn(new_path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use std::{
|
||||
cell::{Ref, RefCell, RefMut},
|
||||
io::Read,
|
||||
path::PathBuf,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
use crate::{
|
||||
assets::{AssetPath, AssetProvider},
|
||||
assets_internal, drawing,
|
||||
@@ -35,6 +38,7 @@ impl Default for Defaults {
|
||||
pub struct Globals {
|
||||
pub assets_internal: Box<dyn AssetProvider>,
|
||||
pub assets_builtin: Box<dyn AssetProvider>,
|
||||
pub asset_folder: PathBuf,
|
||||
pub i18n_builtin: I18n,
|
||||
pub defaults: Defaults,
|
||||
pub font_system: WguiFontSystem,
|
||||
@@ -48,6 +52,7 @@ impl WguiGlobals {
|
||||
mut assets_builtin: Box<dyn AssetProvider>,
|
||||
defaults: Defaults,
|
||||
font_config: &WguiFontConfig,
|
||||
asset_folder: PathBuf,
|
||||
) -> anyhow::Result<Self> {
|
||||
let i18n_builtin = I18n::new(&mut assets_builtin)?;
|
||||
let assets_internal = Box::new(assets_internal::AssetInternal {});
|
||||
@@ -57,6 +62,7 @@ impl WguiGlobals {
|
||||
assets_builtin,
|
||||
i18n_builtin,
|
||||
defaults,
|
||||
asset_folder,
|
||||
font_system: WguiFontSystem::new(font_config),
|
||||
}))))
|
||||
}
|
||||
@@ -65,26 +71,33 @@ impl WguiGlobals {
|
||||
match asset_path {
|
||||
AssetPath::WguiInternal(path) => self.assets_internal().load_from_path(path),
|
||||
AssetPath::BuiltIn(path) => self.assets_builtin().load_from_path(path),
|
||||
AssetPath::Filesystem(path) => {
|
||||
let mut file = match std::fs::File::open(path) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
anyhow::bail!("Could not open asset from {path}: {e}");
|
||||
}
|
||||
};
|
||||
/* 16 MiB safeguard */
|
||||
if file.metadata()?.len() > 16 * 1024 * 1024 {
|
||||
anyhow::bail!("Could not open asset from {path}: Over size limit (16MiB)");
|
||||
}
|
||||
let mut data = Vec::new();
|
||||
if let Err(e) = file.read_to_end(&mut data) {
|
||||
anyhow::bail!("Could not read asset from {path}: {e}");
|
||||
}
|
||||
Ok(data)
|
||||
}
|
||||
AssetPath::FileOrBuiltIn(path) => self
|
||||
.load_asset_from_fs(path)
|
||||
.inspect_err(|e| log::debug!("{e:?}"))
|
||||
.or_else(|_| self.assets_builtin().load_from_path(path)),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_asset_from_fs(&self, path: &str) -> anyhow::Result<Vec<u8>> {
|
||||
let path = self.0.borrow().asset_folder.join(path);
|
||||
let mut file =
|
||||
std::fs::File::open(path.as_path()).with_context(|| format!("Could not open asset from {}", path.display()))?;
|
||||
|
||||
/* 16 MiB safeguard */
|
||||
let metadata = file
|
||||
.metadata()
|
||||
.with_context(|| format!("Could not get file metadata for {}", path.display()))?;
|
||||
|
||||
if metadata.len() > 16 * 1024 * 1024 {
|
||||
anyhow::bail!("Could not open asset from {}: Over size limit (16MiB)", path.display());
|
||||
}
|
||||
let mut data = Vec::new();
|
||||
file
|
||||
.read_to_end(&mut data)
|
||||
.with_context(|| format!("Could not read asset from {}", path.display()))?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn get(&self) -> RefMut<'_, Globals> {
|
||||
self.0.borrow_mut()
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::{
|
||||
assets::AssetPath,
|
||||
components::{Component, button, tooltip},
|
||||
components::{button, tooltip, Component},
|
||||
drawing::Color,
|
||||
i18n::Translation,
|
||||
layout::WidgetID,
|
||||
parser::{
|
||||
AttribPair, ParserContext, ParserFile, parse_check_f32, parse_check_i32, parse_children, print_invalid_attrib,
|
||||
process_component,
|
||||
parse_check_f32, parse_check_i32, parse_children, print_invalid_attrib, process_component,
|
||||
style::{parse_color_opt, parse_round, parse_style, parse_text_style},
|
||||
AttribPair, ParserContext, ParserFile,
|
||||
},
|
||||
widget::util::WLength,
|
||||
};
|
||||
@@ -62,10 +62,10 @@ pub fn parse_component_button<'a>(
|
||||
"hover_border_color" => {
|
||||
parse_color_opt(value, &mut hover_border_color);
|
||||
}
|
||||
"sprite_src" | "sprite_src_ext" | "sprite_src_internal" => {
|
||||
"sprite_src" | "sprite_src_builtin" | "sprite_src_internal" => {
|
||||
let asset_path = match key {
|
||||
"sprite_src" => AssetPath::BuiltIn(value),
|
||||
"sprite_src_ext" => AssetPath::Filesystem(value),
|
||||
"sprite_src" => AssetPath::FileOrBuiltIn(value),
|
||||
"sprite_src_builtin" => AssetPath::BuiltIn(value),
|
||||
"sprite_src_internal" => AssetPath::WguiInternal(value),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@@ -551,7 +551,7 @@ fn parse_tag_include(
|
||||
for pair in attribs {
|
||||
#[allow(clippy::single_match)]
|
||||
match pair.attrib.as_ref() {
|
||||
"src" | "src_ext" | "src_internal" => {
|
||||
"src" | "src_builtin" | "src_internal" => {
|
||||
path = Some({
|
||||
let this = &file.path.clone();
|
||||
let include: &str = &pair.value;
|
||||
@@ -564,9 +564,9 @@ fn parse_tag_include(
|
||||
"src" => match this {
|
||||
AssetPathOwned::WguiInternal(_) => AssetPathOwned::WguiInternal(new_path),
|
||||
AssetPathOwned::BuiltIn(_) => AssetPathOwned::BuiltIn(new_path),
|
||||
AssetPathOwned::Filesystem(_) => AssetPathOwned::Filesystem(new_path),
|
||||
AssetPathOwned::FileOrBuiltIn(_) => AssetPathOwned::FileOrBuiltIn(new_path),
|
||||
},
|
||||
"src_ext" => AssetPathOwned::Filesystem(new_path),
|
||||
"src_builtin" => AssetPathOwned::BuiltIn(new_path),
|
||||
"src_internal" => AssetPathOwned::WguiInternal(new_path),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@@ -583,7 +583,7 @@ fn parse_tag_include(
|
||||
}
|
||||
|
||||
let Some(path) = path else {
|
||||
log::warn!("include tag with no source! specify either: src, src_ext, src_internal");
|
||||
log::warn!("include tag with no source! specify either: src, src_builtin, src_internal");
|
||||
return Ok(());
|
||||
};
|
||||
let path_ref = path.as_ref();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
assets::AssetPath,
|
||||
layout::WidgetID,
|
||||
parser::{AttribPair, ParserContext, ParserFile, parse_children, parse_widget_universal, style::parse_style},
|
||||
parser::{parse_children, parse_widget_universal, style::parse_style, AttribPair, ParserContext, ParserFile},
|
||||
renderer_vk::text::custom_glyph::{CustomGlyphContent, CustomGlyphData},
|
||||
widget::sprite::{WidgetSprite, WidgetSpriteParams},
|
||||
};
|
||||
@@ -22,10 +22,10 @@ pub fn parse_widget_sprite<'a>(
|
||||
for pair in attribs {
|
||||
let (key, value) = (pair.attrib.as_ref(), pair.value.as_ref());
|
||||
match key {
|
||||
"src" | "src_ext" | "src_internal" => {
|
||||
"src" | "src_builtin" | "src_internal" => {
|
||||
let asset_path = match key {
|
||||
"src" => AssetPath::BuiltIn(value),
|
||||
"src_ext" => AssetPath::Filesystem(value),
|
||||
"src" => AssetPath::FileOrBuiltIn(value),
|
||||
"src_builtin" => AssetPath::BuiltIn(value),
|
||||
"src_internal" => AssetPath::WguiInternal(value),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user