Improvements by Nova
This commit is contained in:
@@ -9,7 +9,7 @@ use protostar::{
|
|||||||
use stardust_xr_fusion::{
|
use stardust_xr_fusion::{
|
||||||
client::{Client, FrameInfo, RootHandler},
|
client::{Client, FrameInfo, RootHandler},
|
||||||
core::values::Transform,
|
core::values::Transform,
|
||||||
drawable::{Alignment, Bounds, MaterialParameter, Model, ResourceID, Text, TextFit, TextStyle},
|
drawable::{MaterialParameter, Model, ResourceID},
|
||||||
node::NodeError,
|
node::NodeError,
|
||||||
spatial::Spatial,
|
spatial::Spatial,
|
||||||
};
|
};
|
||||||
@@ -149,7 +149,6 @@ impl RootHandler for AppHexGrid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct App {
|
struct App {
|
||||||
_text: Text,
|
|
||||||
_desktop_file: DesktopFile,
|
_desktop_file: DesktopFile,
|
||||||
protostar: ProtoStar,
|
protostar: ProtoStar,
|
||||||
}
|
}
|
||||||
@@ -161,27 +160,9 @@ impl App {
|
|||||||
desktop_file: DesktopFile,
|
desktop_file: DesktopFile,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
let position = position.into();
|
let position = position.into();
|
||||||
let style = TextStyle {
|
|
||||||
character_height: (APP_SIZE + PADDING) * 0.1,
|
|
||||||
bounds: Some(Bounds {
|
|
||||||
bounds: [(APP_SIZE + PADDING); 2].into(),
|
|
||||||
fit: TextFit::Wrap,
|
|
||||||
bounds_align: Alignment::XCenter | Alignment::YCenter,
|
|
||||||
}),
|
|
||||||
text_align: Alignment::XCenter | Alignment::YCenter,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let protostar =
|
let protostar =
|
||||||
ProtoStar::create_from_desktop_file(parent, position, desktop_file.clone()).ok()?;
|
ProtoStar::create_from_desktop_file(parent, position, desktop_file.clone()).ok()?;
|
||||||
let text = Text::create(
|
|
||||||
protostar.content_parent(),
|
|
||||||
Transform::from_position_rotation([0.0, 0.0, 0.004], Quat::from_rotation_y(PI)),
|
|
||||||
desktop_file.name.as_deref().unwrap_or("Unknown"),
|
|
||||||
style,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
Some(App {
|
Some(App {
|
||||||
_text: text,
|
|
||||||
_desktop_file: desktop_file,
|
_desktop_file: desktop_file,
|
||||||
protostar,
|
protostar,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ async fn main() -> Result<()> {
|
|||||||
parse_desktop_file(desktop_file).map_err(|e| Report::msg(e))?,
|
parse_desktop_file(desktop_file).map_err(|e| Report::msg(e))?,
|
||||||
)?
|
)?
|
||||||
} else if let Some(command) = args.command {
|
} else if let Some(command) = args.command {
|
||||||
ProtoStar::new_raw(client.get_root(), [0.0, 0.0, 0.0], None, command)?
|
ProtoStar::new_raw(client.get_root(), [0.0, 0.0, 0.0], None, None, command)?
|
||||||
} else {
|
} else {
|
||||||
bail!("No command or desktop file, nothing to launch.");
|
bail!("No command or desktop file, nothing to launch.");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use regex::Regex;
|
|||||||
use stardust_xr_fusion::{
|
use stardust_xr_fusion::{
|
||||||
client::{Client, FrameInfo, RootHandler},
|
client::{Client, FrameInfo, RootHandler},
|
||||||
core::values::Transform,
|
core::values::Transform,
|
||||||
drawable::{MaterialParameter, Model, ResourceID},
|
drawable::{Alignment, MaterialParameter, Model, ResourceID, Text, TextStyle},
|
||||||
fields::BoxField,
|
fields::BoxField,
|
||||||
node::NodeType,
|
node::NodeType,
|
||||||
spatial::Spatial,
|
spatial::Spatial,
|
||||||
@@ -62,9 +62,10 @@ pub struct ProtoStar {
|
|||||||
grabbable: Grabbable,
|
grabbable: Grabbable,
|
||||||
field: BoxField,
|
field: BoxField,
|
||||||
icon: Model,
|
icon: Model,
|
||||||
|
label: Option<Text>,
|
||||||
grabbable_shrink: Option<Tweener<f32, f64, QuartInOut>>,
|
grabbable_shrink: Option<Tweener<f32, f64, QuartInOut>>,
|
||||||
grabbable_grow: Option<Tweener<f32, f64, QuartInOut>>,
|
grabbable_grow: Option<Tweener<f32, f64, QuartInOut>>,
|
||||||
grabbabe_move: Option<Tweener<f32, f64, QuartInOut>>,
|
grabbable_move: Option<Tweener<f32, f64, QuartInOut>>,
|
||||||
execute_command: String,
|
execute_command: String,
|
||||||
currently_shown: bool,
|
currently_shown: bool,
|
||||||
}
|
}
|
||||||
@@ -98,6 +99,7 @@ impl ProtoStar {
|
|||||||
Self::new_raw(
|
Self::new_raw(
|
||||||
parent,
|
parent,
|
||||||
position,
|
position,
|
||||||
|
desktop_file.name.as_deref(),
|
||||||
icon,
|
icon,
|
||||||
desktop_file.command.ok_or_else(|| eyre!("No command"))?,
|
desktop_file.command.ok_or_else(|| eyre!("No command"))?,
|
||||||
)
|
)
|
||||||
@@ -105,6 +107,7 @@ impl ProtoStar {
|
|||||||
pub fn new_raw(
|
pub fn new_raw(
|
||||||
parent: &Spatial,
|
parent: &Spatial,
|
||||||
position: impl Into<Vector3<f32>>,
|
position: impl Into<Vector3<f32>>,
|
||||||
|
name: Option<&str>,
|
||||||
icon: Option<Icon>,
|
icon: Option<Icon>,
|
||||||
execute_command: String,
|
execute_command: String,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
@@ -139,31 +142,50 @@ impl ProtoStar {
|
|||||||
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
||||||
)?)
|
)?)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
let label_style = TextStyle {
|
||||||
|
character_height: 0.15,
|
||||||
|
bounds: None,
|
||||||
|
text_align: Alignment::Center.into(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let label = name.and_then(|name| {
|
||||||
|
Text::create(
|
||||||
|
&icon,
|
||||||
|
Transform::from_position_rotation(
|
||||||
|
[0.0, 0.05, -0.6],
|
||||||
|
Quat::from_rotation_x(PI * 0.5),
|
||||||
|
),
|
||||||
|
name,
|
||||||
|
label_style,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
});
|
||||||
Ok(ProtoStar {
|
Ok(ProtoStar {
|
||||||
client: parent.client()?,
|
client: parent.client()?,
|
||||||
position,
|
position,
|
||||||
grabbable,
|
grabbable,
|
||||||
field,
|
field,
|
||||||
|
label,
|
||||||
icon,
|
icon,
|
||||||
grabbable_shrink: None,
|
grabbable_shrink: None,
|
||||||
grabbable_grow: None,
|
grabbable_grow: None,
|
||||||
execute_command,
|
execute_command,
|
||||||
currently_shown: true,
|
currently_shown: true,
|
||||||
grabbabe_move: None,
|
grabbable_move: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn content_parent(&self) -> &Spatial {
|
pub fn content_parent(&self) -> &Spatial {
|
||||||
self.grabbable.content_parent()
|
self.grabbable.content_parent()
|
||||||
}
|
}
|
||||||
pub fn toggle(&mut self) {
|
pub fn toggle(&mut self) {
|
||||||
|
self.grabbable.set_enabled(!self.currently_shown).unwrap();
|
||||||
if self.currently_shown {
|
if self.currently_shown {
|
||||||
self.grabbabe_move = Some(Tweener::quart_in_out(1.0, 0.0001, 0.25)); //TODO make the scale a parameter
|
self.grabbable_move = Some(Tweener::quart_in_out(1.0, 0.0001, 0.25)); //TODO make the scale a parameter
|
||||||
} else {
|
} else {
|
||||||
self.grabbable
|
self.icon.set_enabled(true).unwrap();
|
||||||
.content_parent()
|
self.label.as_ref().map(|l| l.set_enabled(true).unwrap());
|
||||||
.set_scale(None, Vector3::from([1.0; 3]))
|
self.grabbable_move = Some(Tweener::quart_in_out(0.0001, 1.0, 0.25));
|
||||||
.unwrap();
|
|
||||||
self.grabbabe_move = Some(Tweener::quart_in_out(0.0001, 1.0, 0.25));
|
|
||||||
}
|
}
|
||||||
self.currently_shown = !self.currently_shown;
|
self.currently_shown = !self.currently_shown;
|
||||||
}
|
}
|
||||||
@@ -172,9 +194,9 @@ impl RootHandler for ProtoStar {
|
|||||||
fn frame(&mut self, info: FrameInfo) {
|
fn frame(&mut self, info: FrameInfo) {
|
||||||
self.grabbable.update(&info);
|
self.grabbable.update(&info);
|
||||||
|
|
||||||
if let Some(grabbabe_move) = &mut self.grabbabe_move {
|
if let Some(grabbable_move) = &mut self.grabbable_move {
|
||||||
if !grabbabe_move.is_finished() {
|
if !grabbable_move.is_finished() {
|
||||||
let scale = grabbabe_move.move_by(info.delta);
|
let scale = grabbable_move.move_by(info.delta);
|
||||||
self.grabbable
|
self.grabbable
|
||||||
.content_parent()
|
.content_parent()
|
||||||
.set_position(
|
.set_position(
|
||||||
@@ -187,13 +209,11 @@ impl RootHandler for ProtoStar {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
if grabbabe_move.final_value() == 0.0001 {
|
if grabbable_move.final_value() == 0.0001 {
|
||||||
self.grabbable
|
self.icon.set_enabled(false).unwrap();
|
||||||
.content_parent()
|
self.label.as_ref().map(|l| l.set_enabled(false).unwrap());
|
||||||
.set_scale(None, Vector3::from([0.001; 3]))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
self.grabbabe_move = None;
|
self.grabbable_move = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(grabbable_shrink) = &mut self.grabbable_shrink {
|
if let Some(grabbable_shrink) = &mut self.grabbable_shrink {
|
||||||
|
|||||||
13
src/xdg.rs
13
src/xdg.rs
@@ -195,7 +195,9 @@ impl DesktopFile {
|
|||||||
|
|
||||||
let cache_icon_path = get_image_cache_dir().join(icon_name).canonicalize();
|
let cache_icon_path = get_image_cache_dir().join(icon_name).canonicalize();
|
||||||
if cache_icon_path.is_ok() {
|
if cache_icon_path.is_ok() {
|
||||||
return vec![Icon::from_path(cache_icon_path.unwrap(), 128).unwrap()];
|
if let Some(icon) = Icon::from_path(cache_icon_path.unwrap(), 128) {
|
||||||
|
return vec![icon];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut icons_iter = linicon::lookup_icon(icon_name)
|
let mut icons_iter = linicon::lookup_icon(icon_name)
|
||||||
@@ -232,12 +234,11 @@ pub enum IconType {
|
|||||||
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(IconType::Png),
|
Some("png") => IconType::Png,
|
||||||
Some("svg") => Some(IconType::Svg),
|
Some("svg") => IconType::Svg,
|
||||||
Some("glb") | Some("gltf") => Some(IconType::Gltf),
|
Some("glb") | Some("gltf") => IconType::Gltf,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
};
|
||||||
.unwrap();
|
|
||||||
return Some(Icon {
|
return Some(Icon {
|
||||||
icon_type,
|
icon_type,
|
||||||
path,
|
path,
|
||||||
|
|||||||
Reference in New Issue
Block a user