diff --git a/examples/app_grid.rs b/examples/app_grid.rs index 4de4154..658c17a 100644 --- a/examples/app_grid.rs +++ b/examples/app_grid.rs @@ -1,4 +1,5 @@ use color_eyre::eyre::Result; +use glam::Quat; use manifest_dir_macros::directory_relative_path; use mint::Vector3; use protostar::{ @@ -7,10 +8,10 @@ use protostar::{ }; use stardust_xr_fusion::{ client::{Client, FrameInfo, RootHandler}, - spatial::Spatial, + spatial::Spatial, drawable::{Text, TextStyle, Bounds, TextFit, Alignment}, core::values::Transform, }; -const APP_LIMIT: usize = 50; +const APP_LIMIT: usize = 100; const APP_SIZE: f32 = 0.05; const GRID_PADDING: f32 = 0.01; @@ -35,8 +36,10 @@ async fn main() -> Result<()> { struct AppGrid { apps: Vec, + //style: TextStyle, } impl AppGrid { + fn new(client: &Client) -> Self { let apps = get_desktop_files() .into_iter() @@ -53,6 +56,7 @@ impl AppGrid { 0.0, ], a, + //style, ) }) .collect::>(); @@ -67,44 +71,46 @@ impl RootHandler for AppGrid { } } struct App { - // _text: Text, + _text: Text, _desktop_file: DesktopFile, protostar: ProtoStar, } + impl App { fn new( parent: &Spatial, position: impl Into>, desktop_file: DesktopFile, + //style: TextStyle, ) -> Option { let position = position.into(); - + let style = TextStyle { + character_height: APP_SIZE * 0.1, + bounds: Some(Bounds { + bounds: [APP_SIZE; 2].into(), + fit: TextFit::Wrap, + bounds_align: Alignment::XCenter | Alignment::YCenter, + }), + text_align: Alignment::XCenter | Alignment::YCenter, + ..Default::default() + }; let protostar = ProtoStar::create_from_desktop_file(parent, desktop_file.clone()).ok()?; - // let text = Text::create( - // protostar.content_parent(), - // Transform::from_position_rotation( - // [0.0, 0.0, APP_SIZE / 2.0], - // Quat::from_rotation_y(PI), - // ), - // desktop_file.name.as_deref().unwrap_or("Unknown"), - // TextStyle { - // character_height: APP_SIZE * 0.1, - // bounds: Some(Bounds { - // bounds: [APP_SIZE; 2].into(), - // fit: TextFit::Wrap, - // bounds_align: Alignment::XCenter | Alignment::YCenter, - // }), - // text_align: Alignment::XCenter | Alignment::YCenter, - // ..Default::default() - // }, - // ) - // .unwrap(); + let text = Text::create( + protostar.content_parent(), + Transform::from_position_rotation( + [0.0, 0.0, APP_SIZE / 2.0], + Quat::from_rotation_y(3.14), + ), + desktop_file.name.as_deref().unwrap_or("Unknown"), + style, + ) + .unwrap(); protostar .content_parent() .set_position(None, position) .unwrap(); Some(App { - // _text: text, + _text: text, _desktop_file: desktop_file, protostar, }) diff --git a/src/protostar.rs b/src/protostar.rs index 9de8a71..7197703 100644 --- a/src/protostar.rs +++ b/src/protostar.rs @@ -1,4 +1,4 @@ -use crate::xdg::{DesktopFile, Icon, RawIconType}; +use crate::xdg::{DesktopFile, Icon, IconType}; use color_eyre::eyre::{eyre, Result}; use glam::Quat; use mint::Vector3; @@ -19,7 +19,7 @@ use ustr::ustr; fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result { return match &icon.icon_type { - RawIconType::Png(path) => { + IconType::Png(path) => { let model = Model::create( parent, Transform::from_rotation(Quat::from_rotation_y(PI)), @@ -32,7 +32,7 @@ fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result { )?; Ok(model) } - RawIconType::Gltf(path) => Ok(Model::create( + IconType::Gltf(path) => Ok(Model::create( parent, Transform::from_scale([0.05; 3]), &ResourceID::new_direct(path)?, @@ -52,19 +52,29 @@ pub struct ProtoStar { impl ProtoStar { pub fn create_from_desktop_file(parent: &Spatial, desktop_file: DesktopFile) -> Result { // dbg!(&desktop_file); - dbg!(&desktop_file); - let mut raw_icons = dbg!(desktop_file.get_raw_icons()); - let last_icon = raw_icons.pop(); - let icon = raw_icons + let raw_icons = desktop_file.get_raw_icons(); + let mut icon = raw_icons + .clone() .into_iter() .find(|i| match i.icon_type { - RawIconType::Png(_) => false, - RawIconType::Svg(_) => false, - RawIconType::Gltf(_) => true, + IconType::Gltf(_) => true, + _ => false, }) - .or(last_icon) - .map(|i| i.process(128).ok()) - .ok_or_else(|| eyre!("No compatible icons found"))?; + .or( + raw_icons + .into_iter() + .max_by_key(|i| i.size) + ); + + match icon{ + Some(i) => { + icon = match i.process(128) { + Ok(i) => Some(i), + _ => None, + }}, + None => {}, + } + Self::new_raw( parent, icon, diff --git a/src/xdg.rs b/src/xdg.rs index 04f81f2..1530faa 100644 --- a/src/xdg.rs +++ b/src/xdg.rs @@ -9,7 +9,6 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{env, fs}; use walkdir::WalkDir; -use sha2::{Sha224, Digest}; use linicon; fn get_data_dirs() -> Vec { @@ -44,7 +43,6 @@ pub fn get_desktop_files() -> Vec { let desktop_extension = OsString::from_str("desktop").unwrap(); // Get the list of directories to search let app_dirs = get_app_dirs(); - dbg!(&app_dirs); app_dirs .into_iter() .flat_map(|dir| { @@ -180,8 +178,13 @@ impl DesktopFile { } } - let mut icons_iter= linicon::lookup_icon(icon_name); + let mut icons_iter= linicon::lookup_icon(icon_name).use_fallback_themes(false).peekable(); + if icons_iter.peek().is_none(){ + //dbg!("No icons found in current theme"); + icons_iter= linicon::lookup_icon(icon_name).peekable(); + } + let sized_png : Vec = icons_iter .filter_map(|i| i.ok()) .filter(|i| i.icon_type != linicon::IconType::XMP) //TODO: support XMP @@ -191,14 +194,14 @@ impl DesktopFile { } } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct Icon { - pub icon_type: RawIconType, + pub icon_type: IconType, pub size: u16, } -#[derive(Debug, PartialEq, Eq)] -pub enum RawIconType { +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum IconType { Png(PathBuf), Svg(PathBuf), Gltf(PathBuf), @@ -206,9 +209,9 @@ pub enum RawIconType { impl Icon { pub fn from_path(path: PathBuf, size: u16) -> Option{ let icon_type = match path.extension().and_then(|ext| ext.to_str()) { - Some("png") => Some(RawIconType::Png(path)), - Some("svg") => Some(RawIconType::Svg(path)), - Some("glb") | Some("gltf") => Some(RawIconType::Gltf(path)), + Some("png") => Some(IconType::Png(path)), + Some("svg") => Some(IconType::Svg(path)), + Some("glb") | Some("gltf") => Some(IconType::Gltf(path)), _ => {return None}, }.unwrap(); return Some(Icon{icon_type,size}) @@ -216,7 +219,7 @@ impl Icon { pub fn process(self, size: u16) -> Result { match self.icon_type { - RawIconType::Svg(path) => Ok(Icon::from_path(get_png_from_svg(&path, size)?,size).unwrap()), + IconType::Svg(path) => Ok(Icon::from_path(get_png_from_svg(&path, size)?,size).unwrap()), _ => Ok(self), } } @@ -244,8 +247,9 @@ fn test_get_icon_path() { pub fn get_png_from_svg(svg_path: impl AsRef, size: u16,) -> Result { let svg_path = fs::canonicalize(svg_path)?; + let svg_data = fs::read(svg_path.as_path())?; let tree = Tree::from_data( - fs::read(svg_path.as_path())?.as_slice(), + svg_data.as_slice(), &resvg::usvg::Options::default(), ) .map_err(|_| ErrorKind::InvalidData)?; @@ -262,16 +266,9 @@ pub fn get_png_from_svg(svg_path: impl AsRef, size: u16,) -> Result