Added text

This commit is contained in:
nik012003
2023-02-22 23:37:48 +01:00
committed by Nova
parent 64b95441c0
commit a40d0fdd90
3 changed files with 70 additions and 57 deletions

View File

@@ -1,4 +1,5 @@
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use glam::Quat;
use manifest_dir_macros::directory_relative_path; use manifest_dir_macros::directory_relative_path;
use mint::Vector3; use mint::Vector3;
use protostar::{ use protostar::{
@@ -7,10 +8,10 @@ use protostar::{
}; };
use stardust_xr_fusion::{ use stardust_xr_fusion::{
client::{Client, FrameInfo, RootHandler}, 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 APP_SIZE: f32 = 0.05;
const GRID_PADDING: f32 = 0.01; const GRID_PADDING: f32 = 0.01;
@@ -35,8 +36,10 @@ async fn main() -> Result<()> {
struct AppGrid { struct AppGrid {
apps: Vec<App>, apps: Vec<App>,
//style: TextStyle,
} }
impl AppGrid { impl AppGrid {
fn new(client: &Client) -> Self { fn new(client: &Client) -> Self {
let apps = get_desktop_files() let apps = get_desktop_files()
.into_iter() .into_iter()
@@ -53,6 +56,7 @@ impl AppGrid {
0.0, 0.0,
], ],
a, a,
//style,
) )
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@@ -67,44 +71,46 @@ impl RootHandler for AppGrid {
} }
} }
struct App { struct App {
// _text: Text, _text: Text,
_desktop_file: DesktopFile, _desktop_file: DesktopFile,
protostar: ProtoStar, protostar: ProtoStar,
} }
impl App { impl App {
fn new( fn new(
parent: &Spatial, parent: &Spatial,
position: impl Into<Vector3<f32>>, position: impl Into<Vector3<f32>>,
desktop_file: DesktopFile, desktop_file: DesktopFile,
//style: TextStyle,
) -> Option<Self> { ) -> Option<Self> {
let position = position.into(); 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 protostar = ProtoStar::create_from_desktop_file(parent, desktop_file.clone()).ok()?;
// let text = Text::create( let text = Text::create(
// protostar.content_parent(), protostar.content_parent(),
// Transform::from_position_rotation( Transform::from_position_rotation(
// [0.0, 0.0, APP_SIZE / 2.0], [0.0, 0.0, APP_SIZE / 2.0],
// Quat::from_rotation_y(PI), Quat::from_rotation_y(3.14),
// ), ),
// desktop_file.name.as_deref().unwrap_or("Unknown"), desktop_file.name.as_deref().unwrap_or("Unknown"),
// TextStyle { style,
// character_height: APP_SIZE * 0.1, )
// bounds: Some(Bounds { .unwrap();
// bounds: [APP_SIZE; 2].into(),
// fit: TextFit::Wrap,
// bounds_align: Alignment::XCenter | Alignment::YCenter,
// }),
// text_align: Alignment::XCenter | Alignment::YCenter,
// ..Default::default()
// },
// )
// .unwrap();
protostar protostar
.content_parent() .content_parent()
.set_position(None, position) .set_position(None, position)
.unwrap(); .unwrap();
Some(App { Some(App {
// _text: text, _text: text,
_desktop_file: desktop_file, _desktop_file: desktop_file,
protostar, protostar,
}) })

View File

@@ -1,4 +1,4 @@
use crate::xdg::{DesktopFile, Icon, RawIconType}; use crate::xdg::{DesktopFile, Icon, IconType};
use color_eyre::eyre::{eyre, Result}; use color_eyre::eyre::{eyre, Result};
use glam::Quat; use glam::Quat;
use mint::Vector3; use mint::Vector3;
@@ -19,7 +19,7 @@ use ustr::ustr;
fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result<Model> { fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result<Model> {
return match &icon.icon_type { return match &icon.icon_type {
RawIconType::Png(path) => { IconType::Png(path) => {
let model = Model::create( let model = Model::create(
parent, parent,
Transform::from_rotation(Quat::from_rotation_y(PI)), Transform::from_rotation(Quat::from_rotation_y(PI)),
@@ -32,7 +32,7 @@ fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result<Model> {
)?; )?;
Ok(model) Ok(model)
} }
RawIconType::Gltf(path) => Ok(Model::create( IconType::Gltf(path) => Ok(Model::create(
parent, parent,
Transform::from_scale([0.05; 3]), Transform::from_scale([0.05; 3]),
&ResourceID::new_direct(path)?, &ResourceID::new_direct(path)?,
@@ -52,19 +52,29 @@ pub struct ProtoStar {
impl ProtoStar { impl ProtoStar {
pub fn create_from_desktop_file(parent: &Spatial, desktop_file: DesktopFile) -> Result<Self> { pub fn create_from_desktop_file(parent: &Spatial, desktop_file: DesktopFile) -> Result<Self> {
// dbg!(&desktop_file); // dbg!(&desktop_file);
dbg!(&desktop_file); let raw_icons = desktop_file.get_raw_icons();
let mut raw_icons = dbg!(desktop_file.get_raw_icons()); let mut icon = raw_icons
let last_icon = raw_icons.pop(); .clone()
let icon = raw_icons
.into_iter() .into_iter()
.find(|i| match i.icon_type { .find(|i| match i.icon_type {
RawIconType::Png(_) => false, IconType::Gltf(_) => true,
RawIconType::Svg(_) => false, _ => false,
RawIconType::Gltf(_) => true,
}) })
.or(last_icon) .or(
.map(|i| i.process(128).ok()) raw_icons
.ok_or_else(|| eyre!("No compatible icons found"))?; .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( Self::new_raw(
parent, parent,
icon, icon,

View File

@@ -9,7 +9,6 @@ use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use std::{env, fs}; use std::{env, fs};
use walkdir::WalkDir; use walkdir::WalkDir;
use sha2::{Sha224, Digest};
use linicon; use linicon;
fn get_data_dirs() -> Vec<PathBuf> { fn get_data_dirs() -> Vec<PathBuf> {
@@ -44,7 +43,6 @@ pub fn get_desktop_files() -> Vec<PathBuf> {
let desktop_extension = OsString::from_str("desktop").unwrap(); let desktop_extension = OsString::from_str("desktop").unwrap();
// Get the list of directories to search // Get the list of directories to search
let app_dirs = get_app_dirs(); let app_dirs = get_app_dirs();
dbg!(&app_dirs);
app_dirs app_dirs
.into_iter() .into_iter()
.flat_map(|dir| { .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<Icon> = icons_iter let sized_png : Vec<Icon> = icons_iter
.filter_map(|i| i.ok()) .filter_map(|i| i.ok())
.filter(|i| i.icon_type != linicon::IconType::XMP) //TODO: support XMP .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 struct Icon {
pub icon_type: RawIconType, pub icon_type: IconType,
pub size: u16, pub size: u16,
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum RawIconType { pub enum IconType {
Png(PathBuf), Png(PathBuf),
Svg(PathBuf), Svg(PathBuf),
Gltf(PathBuf), Gltf(PathBuf),
@@ -206,9 +209,9 @@ pub enum RawIconType {
impl Icon { impl Icon {
pub fn from_path(path: PathBuf, size: u16) -> Option<Icon>{ pub fn from_path(path: PathBuf, size: u16) -> Option<Icon>{
let icon_type = match path.extension().and_then(|ext| ext.to_str()) { let icon_type = match path.extension().and_then(|ext| ext.to_str()) {
Some("png") => Some(RawIconType::Png(path)), Some("png") => Some(IconType::Png(path)),
Some("svg") => Some(RawIconType::Svg(path)), Some("svg") => Some(IconType::Svg(path)),
Some("glb") | Some("gltf") => Some(RawIconType::Gltf(path)), Some("glb") | Some("gltf") => Some(IconType::Gltf(path)),
_ => {return None}, _ => {return None},
}.unwrap(); }.unwrap();
return Some(Icon{icon_type,size}) return Some(Icon{icon_type,size})
@@ -216,7 +219,7 @@ impl Icon {
pub fn process(self, size: u16) -> Result<Icon, std::io::Error> { pub fn process(self, size: u16) -> Result<Icon, std::io::Error> {
match self.icon_type { 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), _ => Ok(self),
} }
} }
@@ -244,8 +247,9 @@ fn test_get_icon_path() {
pub fn get_png_from_svg(svg_path: impl AsRef<Path>, size: u16,) -> Result<PathBuf, std::io::Error> { pub fn get_png_from_svg(svg_path: impl AsRef<Path>, size: u16,) -> Result<PathBuf, std::io::Error> {
let svg_path = fs::canonicalize(svg_path)?; let svg_path = fs::canonicalize(svg_path)?;
let svg_data = fs::read(svg_path.as_path())?;
let tree = Tree::from_data( let tree = Tree::from_data(
fs::read(svg_path.as_path())?.as_slice(), svg_data.as_slice(),
&resvg::usvg::Options::default(), &resvg::usvg::Options::default(),
) )
.map_err(|_| ErrorKind::InvalidData)?; .map_err(|_| ErrorKind::InvalidData)?;
@@ -262,16 +266,9 @@ pub fn get_png_from_svg(svg_path: impl AsRef<Path>, size: u16,) -> Result<PathBu
let image_cache_dir = cache_dir.join("protostar_icon_cache"); let image_cache_dir = cache_dir.join("protostar_icon_cache");
create_dir_all(&image_cache_dir).expect("Could not create image cache directory"); create_dir_all(&image_cache_dir).expect("Could not create image cache directory");
//TODO: come up with a better way to cache images system
let mut hasher = Sha224::new();
let mut svg_file = fs::File::open(&svg_path)?;
io::copy(&mut svg_file, &mut hasher)?;
let hash_bytes = hasher.finalize();
let png_path = image_cache_dir let png_path = image_cache_dir
.join(format!("{}-{:02x}",svg_path.with_extension("").file_name().unwrap().to_str().unwrap(), hash_bytes)) .join(format!("{}-{}.png",svg_path.file_name().unwrap().to_str().unwrap(), svg_data.len()));
.with_extension("png");
if png_path.exists() { if png_path.exists() {
return Ok(png_path) return Ok(png_path)