feat: upgrade hexagon_launcher with thinner outlines and better colors
This commit is contained in:
36
Cargo.lock
generated
36
Cargo.lock
generated
@@ -141,6 +141,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
|
"color-rs",
|
||||||
"glam",
|
"glam",
|
||||||
"manifest-dir-macros",
|
"manifest-dir-macros",
|
||||||
"mint",
|
"mint",
|
||||||
@@ -702,7 +703,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e31b487427ff5df1386fa4721fcf41923140eb72fc20d776ac95ccbc21fa7bbb"
|
checksum = "e31b487427ff5df1386fa4721fcf41923140eb72fc20d776ac95ccbc21fa7bbb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs 4.0.0",
|
"dirs 4.0.0",
|
||||||
"itertools",
|
"itertools 0.11.0",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rust-ini 0.18.0",
|
"rust-ini 0.18.0",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -849,6 +850,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
|
"color-rs",
|
||||||
"glam",
|
"glam",
|
||||||
"manifest-dir-macros",
|
"manifest-dir-macros",
|
||||||
"mint",
|
"mint",
|
||||||
@@ -960,6 +962,15 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
@@ -1337,7 +1348,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8cad0c4b129e9696e37cb712b243777b90ef489a0bfaa0ac34e7d9b860e4f134"
|
checksum = "8cad0c4b129e9696e37cb712b243777b90ef489a0bfaa0ac34e7d9b860e4f134"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"itertools",
|
"itertools 0.11.0",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1516,7 +1527,7 @@ dependencies = [
|
|||||||
"freedesktop-icons-greedy",
|
"freedesktop-icons-greedy",
|
||||||
"glam",
|
"glam",
|
||||||
"image",
|
"image",
|
||||||
"itertools",
|
"itertools 0.12.0",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"linicon-theme",
|
"linicon-theme",
|
||||||
"manifest-dir-macros",
|
"manifest-dir-macros",
|
||||||
@@ -1920,9 +1931,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_with"
|
name = "serde_with"
|
||||||
version = "3.3.0"
|
version = "3.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237"
|
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -1937,9 +1948,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_with_macros"
|
name = "serde_with_macros"
|
||||||
version = "3.3.0"
|
version = "3.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c"
|
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -1986,6 +1997,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
|
"color-rs",
|
||||||
"glam",
|
"glam",
|
||||||
"manifest-dir-macros",
|
"manifest-dir-macros",
|
||||||
"mint",
|
"mint",
|
||||||
@@ -2009,6 +2021,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
|
"color-rs",
|
||||||
"glam",
|
"glam",
|
||||||
"manifest-dir-macros",
|
"manifest-dir-macros",
|
||||||
"mint",
|
"mint",
|
||||||
@@ -2049,7 +2062,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stardust-xr"
|
name = "stardust-xr"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
source = "git+https://github.com/StardustXR/core.git#7b6c7b1b77075a7035f8a3ef07b430863ed9d60e"
|
source = "git+https://github.com/StardustXR/core.git#975331f9739a9f6cb90ec75813b7720c86225848"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cluFlock",
|
"cluFlock",
|
||||||
"color-rs",
|
"color-rs",
|
||||||
@@ -2069,7 +2082,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stardust-xr-fusion"
|
name = "stardust-xr-fusion"
|
||||||
version = "0.43.2"
|
version = "0.43.2"
|
||||||
source = "git+https://github.com/StardustXR/core.git#7b6c7b1b77075a7035f8a3ef07b430863ed9d60e"
|
source = "git+https://github.com/StardustXR/core.git#975331f9739a9f6cb90ec75813b7720c86225848"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"color-rs",
|
"color-rs",
|
||||||
@@ -2081,6 +2094,7 @@ dependencies = [
|
|||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
|
"serde_with",
|
||||||
"stardust-xr",
|
"stardust-xr",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -2090,7 +2104,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stardust-xr-molecules"
|
name = "stardust-xr-molecules"
|
||||||
version = "0.29.0"
|
version = "0.29.0"
|
||||||
source = "git+https://github.com/StardustXR/molecules.git#6e389f837375a34a10dfd35a633072a77a9f14d8"
|
source = "git+https://github.com/StardustXR/molecules.git#2e60ed7f75a1a79d89b83237dea4d208bc1ab01c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"color-rs",
|
"color-rs",
|
||||||
"glam",
|
"glam",
|
||||||
@@ -2109,7 +2123,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stardust-xr-schemas"
|
name = "stardust-xr-schemas"
|
||||||
version = "1.5.3"
|
version = "1.5.3"
|
||||||
source = "git+https://github.com/StardustXR/core.git#7b6c7b1b77075a7035f8a3ef07b430863ed9d60e"
|
source = "git+https://github.com/StardustXR/core.git#975331f9739a9f6cb90ec75813b7720c86225848"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"flatbuffers",
|
"flatbuffers",
|
||||||
"flexbuffers",
|
"flexbuffers",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
tokio = { version = "1.32.0", features = ["rt", "tokio-macros", "sync"] }
|
tokio = { version = "1.32.0", features = ["rt", "tokio-macros", "sync"] }
|
||||||
protostar = { path = "../protostar" }
|
protostar = { path = "../protostar" }
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
|
color-rs = "0.8.0"
|
||||||
clap = "4.4.6"
|
clap = "4.4.6"
|
||||||
manifest-dir-macros = "0.1.18"
|
manifest-dir-macros = "0.1.18"
|
||||||
glam = "0.24.2"
|
glam = "0.24.2"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use color::rgba_linear;
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{Quat, Vec3};
|
use glam::{Quat, Vec3};
|
||||||
use manifest_dir_macros::directory_relative_path;
|
use manifest_dir_macros::directory_relative_path;
|
||||||
@@ -93,9 +94,10 @@ fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result<Model> {
|
|||||||
Transform::from_rotation(Quat::from_rotation_y(PI)),
|
Transform::from_rotation(Quat::from_rotation_y(PI)),
|
||||||
&ResourceID::new_namespaced("protostar", "cartridge"),
|
&ResourceID::new_namespaced("protostar", "cartridge"),
|
||||||
)?;
|
)?;
|
||||||
model
|
model.model_part("Cartridge")?.set_material_parameter(
|
||||||
.model_part("Cartridge")?
|
"color",
|
||||||
.set_material_parameter("color", MaterialParameter::Color([0.0, 1.0, 1.0, 1.0]))?;
|
MaterialParameter::Color(rgba_linear!(0.0, 1.0, 1.0, 1.0)),
|
||||||
|
)?;
|
||||||
model.model_part("Icon")?.set_material_parameter(
|
model.model_part("Icon")?.set_material_parameter(
|
||||||
"diffuse",
|
"diffuse",
|
||||||
MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())),
|
MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())),
|
||||||
@@ -182,12 +184,12 @@ impl App {
|
|||||||
self.grabbable.content_parent()
|
self.grabbable.content_parent()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bring_back(&self) {
|
// fn bring_back(&self) {
|
||||||
self.grabbable
|
// self.grabbable
|
||||||
.content_parent()
|
// .content_parent()
|
||||||
.set_transform(Some(&self.root), Transform::identity())
|
// .set_transform(Some(&self.root), Transform::identity())
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn frame(&mut self, info: FrameInfo) {
|
fn frame(&mut self, info: FrameInfo) {
|
||||||
let _ = self.grabbable.update(&info);
|
let _ = self.grabbable.update(&info);
|
||||||
@@ -196,23 +198,29 @@ impl App {
|
|||||||
self.grabbable.cancel_angular_velocity();
|
self.grabbable.cancel_angular_velocity();
|
||||||
self.grabbable.cancel_linear_velocity();
|
self.grabbable.cancel_linear_velocity();
|
||||||
|
|
||||||
if !self.grabbable.valid() {
|
// if !self.grabbable.valid() {
|
||||||
self.bring_back();
|
// self.bring_back();
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
let Ok(distance_future) = self.grabbable
|
let Ok(distance_future) = self
|
||||||
|
.grabbable
|
||||||
.content_parent()
|
.content_parent()
|
||||||
.get_position_rotation_scale(&self.root)
|
.get_position_rotation_scale(&self.root)
|
||||||
else {return};
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let application = self.application.clone();
|
let application = self.application.clone();
|
||||||
let space = self.content_parent().alias();
|
let space = self.content_parent().alias();
|
||||||
let root = self.root.alias();
|
let root = self.root.alias();
|
||||||
|
|
||||||
tokio::task::spawn(async move {
|
tokio::task::spawn(async move {
|
||||||
let Ok((distance, _rotation, _scale)) = distance_future.await else { space
|
let Ok((distance, _rotation, _scale)) = distance_future.await else {
|
||||||
.set_transform(Some(&root), Transform::identity())
|
space
|
||||||
.unwrap(); return};
|
.set_transform(Some(&root), Transform::identity())
|
||||||
|
.unwrap();
|
||||||
|
return;
|
||||||
|
};
|
||||||
let distance = Vec3::from(distance).length_squared();
|
let distance = Vec3::from(distance).length_squared();
|
||||||
|
|
||||||
if distance > ACTIVATION_DISTANCE.powi(2) {
|
if distance > ACTIVATION_DISTANCE.powi(2) {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -6,6 +6,7 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.32.0", features = ["rt", "tokio-macros", "sync"] }
|
tokio = { version = "1.32.0", features = ["rt", "tokio-macros", "sync"] }
|
||||||
protostar = { path = "../protostar" }
|
protostar = { path = "../protostar" }
|
||||||
|
color-rs = "0.8.0"
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
clap = "4.4.6"
|
clap = "4.4.6"
|
||||||
manifest-dir-macros = "0.1.18"
|
manifest-dir-macros = "0.1.18"
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"asset":{
|
"asset":{
|
||||||
"generator":"Khronos glTF Blender I/O v3.5.30",
|
"generator":"Khronos glTF Blender I/O v3.6.6",
|
||||||
"version":"2.0"
|
"version":"2.0"
|
||||||
},
|
},
|
||||||
"extensionsUsed":[
|
"extensionsUsed":[
|
||||||
@@ -51,9 +51,9 @@
|
|||||||
"name":"Hex",
|
"name":"Hex",
|
||||||
"pbrMetallicRoughness":{
|
"pbrMetallicRoughness":{
|
||||||
"baseColorFactor":[
|
"baseColorFactor":[
|
||||||
1,
|
0.9720873236656189,
|
||||||
0,
|
0.018567396327853203,
|
||||||
0,
|
0.017742767930030823,
|
||||||
1
|
1
|
||||||
],
|
],
|
||||||
"baseColorTexture":{
|
"baseColorTexture":{
|
||||||
@@ -173,14 +173,14 @@
|
|||||||
"componentType":5126,
|
"componentType":5126,
|
||||||
"count":54,
|
"count":54,
|
||||||
"max":[
|
"max":[
|
||||||
1.0441828966140747,
|
1.0166369676589966,
|
||||||
0.05000000074505806,
|
0.021040409803390503,
|
||||||
0.9042890667915344
|
0.8804334998130798
|
||||||
],
|
],
|
||||||
"min":[
|
"min":[
|
||||||
-1.0441828966140747,
|
-1.0166369676589966,
|
||||||
0,
|
-7.071532309055328e-06,
|
||||||
-0.9042890667915344
|
-0.8804334998130798
|
||||||
],
|
],
|
||||||
"type":"VEC3"
|
"type":"VEC3"
|
||||||
},
|
},
|
||||||
|
|||||||
256
hexagon_launcher/src/app.rs
Normal file
256
hexagon_launcher/src/app.rs
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
use color_eyre::eyre::Result;
|
||||||
|
use glam::{EulerRot, Quat, Vec3};
|
||||||
|
use mint::Vector3;
|
||||||
|
use protostar::{
|
||||||
|
application::Application,
|
||||||
|
xdg::{DesktopFile, Icon, IconType},
|
||||||
|
};
|
||||||
|
use stardust_xr_fusion::{
|
||||||
|
client::FrameInfo,
|
||||||
|
core::values::Transform,
|
||||||
|
drawable::{Alignment, Bounds, MaterialParameter, Model, ResourceID, Text, TextFit, TextStyle},
|
||||||
|
fields::BoxField,
|
||||||
|
node::NodeType,
|
||||||
|
spatial::Spatial,
|
||||||
|
};
|
||||||
|
use stardust_xr_molecules::{Grabbable, GrabbableSettings};
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
use tween::{QuartInOut, Tweener};
|
||||||
|
|
||||||
|
use crate::{ACTIVATION_DISTANCE, APP_SIZE, DEFAULT_HEX_COLOR};
|
||||||
|
|
||||||
|
// Model handling
|
||||||
|
fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result<Model> {
|
||||||
|
match &icon.icon_type {
|
||||||
|
IconType::Png => {
|
||||||
|
let t = Transform::from_rotation_scale(
|
||||||
|
Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI),
|
||||||
|
[APP_SIZE / 2.0; 3],
|
||||||
|
);
|
||||||
|
|
||||||
|
let model = Model::create(
|
||||||
|
parent,
|
||||||
|
t,
|
||||||
|
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
||||||
|
)?;
|
||||||
|
model
|
||||||
|
.model_part("Hex")?
|
||||||
|
.set_material_parameter("color", MaterialParameter::Color(DEFAULT_HEX_COLOR))?;
|
||||||
|
model.model_part("Icon")?.set_material_parameter(
|
||||||
|
"diffuse",
|
||||||
|
MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())),
|
||||||
|
)?;
|
||||||
|
Ok(model)
|
||||||
|
}
|
||||||
|
IconType::Gltf => Ok(Model::create(
|
||||||
|
parent,
|
||||||
|
Transform::from_scale([0.05; 3]),
|
||||||
|
&ResourceID::new_direct(icon.path.clone())?,
|
||||||
|
)?),
|
||||||
|
_ => panic!("Invalid Icon Type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct App {
|
||||||
|
application: Application,
|
||||||
|
parent: Spatial,
|
||||||
|
position: Vector3<f32>,
|
||||||
|
grabbable: Grabbable,
|
||||||
|
_field: BoxField,
|
||||||
|
icon: Model,
|
||||||
|
label: Option<Text>,
|
||||||
|
grabbable_shrink: Option<Tweener<f32, f64, QuartInOut>>,
|
||||||
|
grabbable_grow: Option<Tweener<f32, f64, QuartInOut>>,
|
||||||
|
grabbable_move: Option<Tweener<f32, f64, QuartInOut>>,
|
||||||
|
currently_shown: bool,
|
||||||
|
}
|
||||||
|
impl App {
|
||||||
|
pub fn create_from_desktop_file(
|
||||||
|
parent: &Spatial,
|
||||||
|
position: impl Into<Vector3<f32>>,
|
||||||
|
desktop_file: DesktopFile,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let position = position.into();
|
||||||
|
let field = BoxField::create(parent, Transform::default(), [APP_SIZE; 3])?;
|
||||||
|
let application = Application::create(desktop_file)?;
|
||||||
|
let icon = application.icon(128, false);
|
||||||
|
let grabbable = Grabbable::create(
|
||||||
|
parent,
|
||||||
|
Transform::from_position(position),
|
||||||
|
&field,
|
||||||
|
GrabbableSettings {
|
||||||
|
max_distance: 0.01,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
grabbable.content_parent().set_spatial_parent(parent)?;
|
||||||
|
field.set_spatial_parent(grabbable.content_parent())?;
|
||||||
|
let icon = icon
|
||||||
|
.map(|i| model_from_icon(grabbable.content_parent(), &i))
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
Ok(Model::create(
|
||||||
|
grabbable.content_parent(),
|
||||||
|
Transform::from_rotation_scale(
|
||||||
|
Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI),
|
||||||
|
[APP_SIZE * 0.5; 3],
|
||||||
|
),
|
||||||
|
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
||||||
|
)?)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let label_style = TextStyle {
|
||||||
|
character_height: APP_SIZE * 2.0,
|
||||||
|
bounds: Some(Bounds {
|
||||||
|
bounds: [1.0; 2].into(),
|
||||||
|
fit: TextFit::Wrap,
|
||||||
|
bounds_align: Alignment::XCenter | Alignment::YCenter,
|
||||||
|
}),
|
||||||
|
text_align: Alignment::Center.into(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let label = application.name().and_then(|name| {
|
||||||
|
Text::create(
|
||||||
|
&icon,
|
||||||
|
Transform::from_position_rotation(
|
||||||
|
[0.0, 0.1, -(APP_SIZE * 4.0)],
|
||||||
|
Quat::from_rotation_x(PI * 0.5),
|
||||||
|
),
|
||||||
|
name,
|
||||||
|
label_style,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
});
|
||||||
|
Ok(App {
|
||||||
|
parent: parent.alias(),
|
||||||
|
position,
|
||||||
|
grabbable,
|
||||||
|
_field: field,
|
||||||
|
label,
|
||||||
|
application,
|
||||||
|
icon,
|
||||||
|
grabbable_shrink: None,
|
||||||
|
grabbable_grow: None,
|
||||||
|
grabbable_move: None,
|
||||||
|
currently_shown: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn content_parent(&self) -> &Spatial {
|
||||||
|
self.grabbable.content_parent()
|
||||||
|
}
|
||||||
|
pub fn toggle(&mut self) {
|
||||||
|
self.grabbable.set_enabled(!self.currently_shown).unwrap();
|
||||||
|
if self.currently_shown {
|
||||||
|
self.grabbable_move = Some(Tweener::quart_in_out(1.0, 0.0001, 0.25)); //TODO make the scale a parameter
|
||||||
|
} else {
|
||||||
|
self.icon.set_enabled(true).unwrap();
|
||||||
|
if let Some(label) = self.label.as_ref() {
|
||||||
|
label.set_enabled(true).unwrap()
|
||||||
|
}
|
||||||
|
self.grabbable_move = Some(Tweener::quart_in_out(0.0001, 1.0, 0.25));
|
||||||
|
}
|
||||||
|
self.currently_shown = !self.currently_shown;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn frame(&mut self, info: FrameInfo) {
|
||||||
|
let _ = self.grabbable.update(&info);
|
||||||
|
|
||||||
|
if let Some(grabbable_move) = &mut self.grabbable_move {
|
||||||
|
if !grabbable_move.is_finished() {
|
||||||
|
let scale = grabbable_move.move_by(info.delta);
|
||||||
|
self.grabbable
|
||||||
|
.content_parent()
|
||||||
|
.set_position(Some(&self.parent), Vec3::from(self.position) * scale)
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
if grabbable_move.final_value() == 0.0001 {
|
||||||
|
self.icon.set_enabled(false).unwrap();
|
||||||
|
if let Some(label) = self.label.as_ref() {
|
||||||
|
label.set_enabled(false).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.grabbable_move = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(grabbable_shrink) = &mut self.grabbable_shrink {
|
||||||
|
if !grabbable_shrink.is_finished() {
|
||||||
|
let scale = grabbable_shrink.move_by(info.delta);
|
||||||
|
self.grabbable
|
||||||
|
.content_parent()
|
||||||
|
.set_scale(Some(&self.parent), Vector3::from([scale; 3]))
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
self.grabbable
|
||||||
|
.content_parent()
|
||||||
|
.set_spatial_parent(&self.parent)
|
||||||
|
.unwrap();
|
||||||
|
if self.currently_shown {
|
||||||
|
self.grabbable_grow = Some(Tweener::quart_in_out(0.0001, 1.0, 0.25));
|
||||||
|
self.grabbable.cancel_angular_velocity();
|
||||||
|
self.grabbable.cancel_linear_velocity();
|
||||||
|
}
|
||||||
|
self.grabbable_shrink = None;
|
||||||
|
self.grabbable
|
||||||
|
.content_parent()
|
||||||
|
.set_position(Some(&self.parent), self.position)
|
||||||
|
.unwrap();
|
||||||
|
self.grabbable
|
||||||
|
.content_parent()
|
||||||
|
.set_rotation(Some(&self.parent), Quat::default())
|
||||||
|
.unwrap();
|
||||||
|
self.icon
|
||||||
|
.set_rotation(
|
||||||
|
None,
|
||||||
|
Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
} else if let Some(grabbable_grow) = &mut self.grabbable_grow {
|
||||||
|
if !grabbable_grow.is_finished() {
|
||||||
|
let scale = grabbable_grow.move_by(info.delta);
|
||||||
|
self.grabbable
|
||||||
|
.content_parent()
|
||||||
|
.set_scale(Some(&self.parent), Vector3::from([scale; 3]))
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
self.grabbable
|
||||||
|
.content_parent()
|
||||||
|
.set_spatial_parent(&self.parent)
|
||||||
|
.unwrap();
|
||||||
|
self.grabbable_grow = None;
|
||||||
|
}
|
||||||
|
} else if self.grabbable.grab_action().actor_stopped() {
|
||||||
|
self.grabbable_shrink = Some(Tweener::quart_in_out(APP_SIZE * 0.5, 0.0001, 0.25));
|
||||||
|
let Ok(distance_future) = self
|
||||||
|
.grabbable
|
||||||
|
.content_parent()
|
||||||
|
.get_position_rotation_scale(&self.parent)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let application = self.application.clone();
|
||||||
|
let space = self.content_parent().alias();
|
||||||
|
|
||||||
|
//TODO: split the executable string for the args
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
let distance_vector = distance_future.await.ok().unwrap().0;
|
||||||
|
let distance = Vec3::from(distance_vector).length_squared();
|
||||||
|
|
||||||
|
if distance > ACTIVATION_DISTANCE {
|
||||||
|
let client = space.node().client().unwrap();
|
||||||
|
let (_, space_rot, _) = space
|
||||||
|
.get_position_rotation_scale(&client.get_root())
|
||||||
|
.unwrap()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let (_, y_rot, _) = Quat::from(space_rot).to_euler(EulerRot::XYZ);
|
||||||
|
let _ = space.set_transform(
|
||||||
|
Some(client.get_root()),
|
||||||
|
Transform::from_rotation_scale(Quat::from_rotation_y(y_rot), [1.0; 3]),
|
||||||
|
);
|
||||||
|
let _ = application.launch(&space);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,31 @@
|
|||||||
|
pub mod app;
|
||||||
pub mod hex;
|
pub mod hex;
|
||||||
|
|
||||||
|
use app::App;
|
||||||
|
use color::{color_space::LinearRgb, rgba_linear, Rgba};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{EulerRot, Quat, Vec3};
|
use glam::Quat;
|
||||||
use hex::{HEX_CENTER, HEX_DIRECTION_VECTORS};
|
use hex::{HEX_CENTER, HEX_DIRECTION_VECTORS};
|
||||||
use manifest_dir_macros::directory_relative_path;
|
use manifest_dir_macros::directory_relative_path;
|
||||||
use mint::Vector3;
|
use protostar::xdg::{get_desktop_files, parse_desktop_file, DesktopFile};
|
||||||
use protostar::{
|
|
||||||
application::Application,
|
|
||||||
xdg::{get_desktop_files, parse_desktop_file, DesktopFile, Icon, IconType},
|
|
||||||
};
|
|
||||||
use stardust_xr_fusion::{
|
use stardust_xr_fusion::{
|
||||||
client::{Client, ClientState, FrameInfo, RootHandler},
|
client::{Client, ClientState, FrameInfo, RootHandler},
|
||||||
core::values::Transform,
|
core::values::Transform,
|
||||||
drawable::{Alignment, Bounds, MaterialParameter, Model, ResourceID, Text, TextFit, TextStyle},
|
drawable::{MaterialParameter, Model, ResourceID},
|
||||||
fields::BoxField,
|
fields::BoxField,
|
||||||
node::NodeError,
|
node::NodeError,
|
||||||
node::NodeType,
|
|
||||||
spatial::Spatial,
|
|
||||||
};
|
};
|
||||||
use stardust_xr_molecules::{touch_plane::TouchPlane, Grabbable, GrabbableSettings};
|
use stardust_xr_molecules::{touch_plane::TouchPlane, Grabbable, GrabbableSettings, PointerMode};
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use tween::{QuartInOut, Tweener};
|
|
||||||
|
|
||||||
const APP_SIZE: f32 = 0.06;
|
const APP_SIZE: f32 = 0.06;
|
||||||
const PADDING: f32 = 0.005;
|
const PADDING: f32 = 0.005;
|
||||||
const MODEL_SCALE: f32 = 0.03;
|
const MODEL_SCALE: f32 = 0.03;
|
||||||
const ACTIVATION_DISTANCE: f32 = 0.05;
|
const ACTIVATION_DISTANCE: f32 = 0.05;
|
||||||
|
|
||||||
const CYAN: [f32; 4] = [0.0, 1.0, 1.0, 1.0];
|
const DEFAULT_HEX_COLOR: Rgba<f32, LinearRgb> = rgba_linear!(0.211, 0.937, 0.588, 1.0);
|
||||||
const BTN_SELECTED_COLOR: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
|
const BTN_SELECTED_COLOR: Rgba<f32, LinearRgb> = rgba_linear!(0.0, 1.0, 0.0, 1.0);
|
||||||
const BTN_COLOR: [f32; 4] = [1.0, 1.0, 0.0, 1.0];
|
const BTN_COLOR: Rgba<f32, LinearRgb> = rgba_linear!(1.0, 1.0, 0.0, 1.0);
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
@@ -137,6 +133,8 @@ impl Button {
|
|||||||
&field,
|
&field,
|
||||||
GrabbableSettings {
|
GrabbableSettings {
|
||||||
max_distance: 0.01,
|
max_distance: 0.01,
|
||||||
|
pointer_mode: PointerMode::Align,
|
||||||
|
magnet: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
@@ -179,236 +177,3 @@ impl Button {
|
|||||||
self.touch_plane.update();
|
self.touch_plane.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Model handling
|
|
||||||
fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result<Model> {
|
|
||||||
match &icon.icon_type {
|
|
||||||
IconType::Png => {
|
|
||||||
let t = Transform::from_rotation_scale(
|
|
||||||
Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI),
|
|
||||||
[APP_SIZE / 2.0; 3],
|
|
||||||
);
|
|
||||||
|
|
||||||
let model = Model::create(
|
|
||||||
parent,
|
|
||||||
t,
|
|
||||||
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
|
||||||
)?;
|
|
||||||
model
|
|
||||||
.model_part("Hex")?
|
|
||||||
.set_material_parameter("color", MaterialParameter::Color(CYAN))?;
|
|
||||||
model.model_part("Icon")?.set_material_parameter(
|
|
||||||
"diffuse",
|
|
||||||
MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())),
|
|
||||||
)?;
|
|
||||||
Ok(model)
|
|
||||||
}
|
|
||||||
IconType::Gltf => Ok(Model::create(
|
|
||||||
parent,
|
|
||||||
Transform::from_scale([0.05; 3]),
|
|
||||||
&ResourceID::new_direct(icon.path.clone())?,
|
|
||||||
)?),
|
|
||||||
_ => panic!("Invalid Icon Type"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct App {
|
|
||||||
application: Application,
|
|
||||||
parent: Spatial,
|
|
||||||
position: Vector3<f32>,
|
|
||||||
grabbable: Grabbable,
|
|
||||||
_field: BoxField,
|
|
||||||
icon: Model,
|
|
||||||
label: Option<Text>,
|
|
||||||
grabbable_shrink: Option<Tweener<f32, f64, QuartInOut>>,
|
|
||||||
grabbable_grow: Option<Tweener<f32, f64, QuartInOut>>,
|
|
||||||
grabbable_move: Option<Tweener<f32, f64, QuartInOut>>,
|
|
||||||
currently_shown: bool,
|
|
||||||
}
|
|
||||||
impl App {
|
|
||||||
pub fn create_from_desktop_file(
|
|
||||||
parent: &Spatial,
|
|
||||||
position: impl Into<Vector3<f32>>,
|
|
||||||
desktop_file: DesktopFile,
|
|
||||||
) -> Result<Self> {
|
|
||||||
let position = position.into();
|
|
||||||
let field = BoxField::create(parent, Transform::default(), [APP_SIZE; 3])?;
|
|
||||||
let application = Application::create(desktop_file)?;
|
|
||||||
let icon = application.icon(128, false);
|
|
||||||
let grabbable = Grabbable::create(
|
|
||||||
parent,
|
|
||||||
Transform::from_position(position),
|
|
||||||
&field,
|
|
||||||
GrabbableSettings {
|
|
||||||
max_distance: 0.01,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
grabbable.content_parent().set_spatial_parent(parent)?;
|
|
||||||
field.set_spatial_parent(grabbable.content_parent())?;
|
|
||||||
let icon = icon
|
|
||||||
.map(|i| model_from_icon(grabbable.content_parent(), &i))
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
Ok(Model::create(
|
|
||||||
grabbable.content_parent(),
|
|
||||||
Transform::from_rotation_scale(
|
|
||||||
Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI),
|
|
||||||
[APP_SIZE * 0.5; 3],
|
|
||||||
),
|
|
||||||
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
|
||||||
)?)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let label_style = TextStyle {
|
|
||||||
character_height: APP_SIZE * 2.0,
|
|
||||||
bounds: Some(Bounds {
|
|
||||||
bounds: [1.0; 2].into(),
|
|
||||||
fit: TextFit::Wrap,
|
|
||||||
bounds_align: Alignment::XCenter | Alignment::YCenter,
|
|
||||||
}),
|
|
||||||
text_align: Alignment::Center.into(),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let label = application.name().and_then(|name| {
|
|
||||||
Text::create(
|
|
||||||
&icon,
|
|
||||||
Transform::from_position_rotation(
|
|
||||||
[0.0, 0.1, -(APP_SIZE * 4.0)],
|
|
||||||
Quat::from_rotation_x(PI * 0.5),
|
|
||||||
),
|
|
||||||
name,
|
|
||||||
label_style,
|
|
||||||
)
|
|
||||||
.ok()
|
|
||||||
});
|
|
||||||
Ok(App {
|
|
||||||
parent: parent.alias(),
|
|
||||||
position,
|
|
||||||
grabbable,
|
|
||||||
_field: field,
|
|
||||||
label,
|
|
||||||
application,
|
|
||||||
icon,
|
|
||||||
grabbable_shrink: None,
|
|
||||||
grabbable_grow: None,
|
|
||||||
grabbable_move: None,
|
|
||||||
currently_shown: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pub fn content_parent(&self) -> &Spatial {
|
|
||||||
self.grabbable.content_parent()
|
|
||||||
}
|
|
||||||
pub fn toggle(&mut self) {
|
|
||||||
self.grabbable.set_enabled(!self.currently_shown).unwrap();
|
|
||||||
if self.currently_shown {
|
|
||||||
self.grabbable_move = Some(Tweener::quart_in_out(1.0, 0.0001, 0.25)); //TODO make the scale a parameter
|
|
||||||
} else {
|
|
||||||
self.icon.set_enabled(true).unwrap();
|
|
||||||
if let Some(label) = self.label.as_ref() {
|
|
||||||
label.set_enabled(true).unwrap()
|
|
||||||
}
|
|
||||||
self.grabbable_move = Some(Tweener::quart_in_out(0.0001, 1.0, 0.25));
|
|
||||||
}
|
|
||||||
self.currently_shown = !self.currently_shown;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn frame(&mut self, info: FrameInfo) {
|
|
||||||
let _ = self.grabbable.update(&info);
|
|
||||||
|
|
||||||
if let Some(grabbable_move) = &mut self.grabbable_move {
|
|
||||||
if !grabbable_move.is_finished() {
|
|
||||||
let scale = grabbable_move.move_by(info.delta);
|
|
||||||
self.grabbable
|
|
||||||
.content_parent()
|
|
||||||
.set_position(Some(&self.parent), Vec3::from(self.position) * scale)
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
|
||||||
if grabbable_move.final_value() == 0.0001 {
|
|
||||||
self.icon.set_enabled(false).unwrap();
|
|
||||||
if let Some(label) = self.label.as_ref() {
|
|
||||||
label.set_enabled(false).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.grabbable_move = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(grabbable_shrink) = &mut self.grabbable_shrink {
|
|
||||||
if !grabbable_shrink.is_finished() {
|
|
||||||
let scale = grabbable_shrink.move_by(info.delta);
|
|
||||||
self.grabbable
|
|
||||||
.content_parent()
|
|
||||||
.set_scale(Some(&self.parent), Vector3::from([scale; 3]))
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
|
||||||
self.grabbable
|
|
||||||
.content_parent()
|
|
||||||
.set_spatial_parent(&self.parent)
|
|
||||||
.unwrap();
|
|
||||||
if self.currently_shown {
|
|
||||||
self.grabbable_grow = Some(Tweener::quart_in_out(0.0001, 1.0, 0.25));
|
|
||||||
self.grabbable.cancel_angular_velocity();
|
|
||||||
self.grabbable.cancel_linear_velocity();
|
|
||||||
}
|
|
||||||
self.grabbable_shrink = None;
|
|
||||||
self.grabbable
|
|
||||||
.content_parent()
|
|
||||||
.set_position(Some(&self.parent), self.position)
|
|
||||||
.unwrap();
|
|
||||||
self.grabbable
|
|
||||||
.content_parent()
|
|
||||||
.set_rotation(Some(&self.parent), Quat::default())
|
|
||||||
.unwrap();
|
|
||||||
self.icon
|
|
||||||
.set_rotation(
|
|
||||||
None,
|
|
||||||
Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
} else if let Some(grabbable_grow) = &mut self.grabbable_grow {
|
|
||||||
if !grabbable_grow.is_finished() {
|
|
||||||
let scale = grabbable_grow.move_by(info.delta);
|
|
||||||
self.grabbable
|
|
||||||
.content_parent()
|
|
||||||
.set_scale(Some(&self.parent), Vector3::from([scale; 3]))
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
|
||||||
self.grabbable
|
|
||||||
.content_parent()
|
|
||||||
.set_spatial_parent(&self.parent)
|
|
||||||
.unwrap();
|
|
||||||
self.grabbable_grow = None;
|
|
||||||
}
|
|
||||||
} else if self.grabbable.valid() && self.grabbable.grab_action().actor_stopped() {
|
|
||||||
self.grabbable_shrink = Some(Tweener::quart_in_out(APP_SIZE * 0.5, 0.0001, 0.25));
|
|
||||||
let Ok(distance_future) = self.grabbable
|
|
||||||
.content_parent()
|
|
||||||
.get_position_rotation_scale(&self.parent)
|
|
||||||
else {return};
|
|
||||||
|
|
||||||
let application = self.application.clone();
|
|
||||||
let space = self.content_parent().alias();
|
|
||||||
|
|
||||||
//TODO: split the executable string for the args
|
|
||||||
tokio::task::spawn(async move {
|
|
||||||
let distance_vector = distance_future.await.ok().unwrap().0;
|
|
||||||
let distance = Vec3::from(distance_vector).length_squared();
|
|
||||||
|
|
||||||
if distance > ACTIVATION_DISTANCE {
|
|
||||||
let client = space.node().client().unwrap();
|
|
||||||
let (_, space_rot, _) = space
|
|
||||||
.get_position_rotation_scale(&client.get_root())
|
|
||||||
.unwrap()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
let (_, y_rot, _) = Quat::from(space_rot).to_euler(EulerRot::XYZ);
|
|
||||||
let _ = space.set_transform(
|
|
||||||
Some(client.get_root()),
|
|
||||||
Transform::from_rotation_scale(Quat::from_rotation_y(y_rot), [1.0; 3]),
|
|
||||||
);
|
|
||||||
let _ = application.launch(&space);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ ez-pixmap = "0.2.2"
|
|||||||
freedesktop-icons-greedy = "0.2.6"
|
freedesktop-icons-greedy = "0.2.6"
|
||||||
glam = { version = "0.24.0", features = ["mint"] }
|
glam = { version = "0.24.0", features = ["mint"] }
|
||||||
image = "0.24.5"
|
image = "0.24.5"
|
||||||
itertools = "0.11.0"
|
itertools = "0.12.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
linicon-theme = "1.2.0"
|
linicon-theme = "1.2.0"
|
||||||
manifest-dir-macros = "0.1.16"
|
manifest-dir-macros = "0.1.16"
|
||||||
@@ -22,7 +22,7 @@ regex = "1.7.1"
|
|||||||
resvg = "0.29.0"
|
resvg = "0.29.0"
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
serde = "1.0.155"
|
serde = "1.0.155"
|
||||||
serde_with = "3.3.0"
|
serde_with = "3.4.0"
|
||||||
tokio = { version = "1.24.1", features = ["full"] }
|
tokio = { version = "1.24.1", features = ["full"] }
|
||||||
toml = "0.8.2"
|
toml = "0.8.2"
|
||||||
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
tokio = { version = "1.32.0", features = ["rt", "tokio-macros", "sync"] }
|
tokio = { version = "1.32.0", features = ["rt", "tokio-macros", "sync"] }
|
||||||
protostar = { path = "../protostar" }
|
protostar = { path = "../protostar" }
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
|
color-rs = "0.8.0"
|
||||||
clap = "4.4.6"
|
clap = "4.4.6"
|
||||||
manifest-dir-macros = "0.1.18"
|
manifest-dir-macros = "0.1.18"
|
||||||
glam = "0.24.2"
|
glam = "0.24.2"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use color::rgba_linear;
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{Quat, Vec3};
|
use glam::{Quat, Vec3};
|
||||||
use mint::Vector3;
|
use mint::Vector3;
|
||||||
@@ -33,9 +34,10 @@ fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result<Model> {
|
|||||||
t,
|
t,
|
||||||
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
||||||
)?;
|
)?;
|
||||||
model
|
model.model_part("Hex")?.set_material_parameter(
|
||||||
.model_part("Hex")?
|
"color",
|
||||||
.set_material_parameter("color", MaterialParameter::Color([0.0, 1.0, 1.0, 1.0]))?;
|
MaterialParameter::Color(rgba_linear!(0.0, 1.0, 1.0, 1.0)),
|
||||||
|
)?;
|
||||||
model.model_part("Icon")?.set_material_parameter(
|
model.model_part("Icon")?.set_material_parameter(
|
||||||
"diffuse",
|
"diffuse",
|
||||||
MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())),
|
MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())),
|
||||||
@@ -211,12 +213,15 @@ impl RootHandler for Single {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
self.grabbable_grow = None;
|
self.grabbable_grow = None;
|
||||||
}
|
}
|
||||||
} else if self.grabbable.valid() && self.grabbable.grab_action().actor_stopped() {
|
} else if self.grabbable.grab_action().actor_stopped() {
|
||||||
self.grabbable_shrink = Some(Tweener::quart_in_out(MODEL_SCALE, 0.0001, 0.25));
|
self.grabbable_shrink = Some(Tweener::quart_in_out(MODEL_SCALE, 0.0001, 0.25));
|
||||||
let Ok(distance_future) = self.grabbable
|
let Ok(distance_future) = self
|
||||||
|
.grabbable
|
||||||
.content_parent()
|
.content_parent()
|
||||||
.get_position_rotation_scale(&self.parent)
|
.get_position_rotation_scale(&self.parent)
|
||||||
else {return};
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let application = self.application.clone();
|
let application = self.application.clone();
|
||||||
let space = self.content_parent().alias();
|
let space = self.content_parent().alias();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
tokio = { version = "1.32.0", features = ["rt", "tokio-macros", "sync"] }
|
tokio = { version = "1.32.0", features = ["rt", "tokio-macros", "sync"] }
|
||||||
protostar = { path = "../protostar" }
|
protostar = { path = "../protostar" }
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
|
color-rs = "0.8.0"
|
||||||
clap = "4.4.6"
|
clap = "4.4.6"
|
||||||
manifest-dir-macros = "0.1.18"
|
manifest-dir-macros = "0.1.18"
|
||||||
glam = "0.24.2"
|
glam = "0.24.2"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use clap::{self, Parser};
|
use clap::{self, Parser};
|
||||||
|
use color::rgba_linear;
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{Quat, Vec3};
|
use glam::{Quat, Vec3};
|
||||||
use manifest_dir_macros::directory_relative_path;
|
use manifest_dir_macros::directory_relative_path;
|
||||||
@@ -164,36 +165,40 @@ impl RootHandler for Sirius {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let color = [0.0, 1.0, 0.0, 1.0];
|
|
||||||
self.model
|
self.model
|
||||||
.model_part("?????")
|
.model_part("?????")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_material_parameter("color", MaterialParameter::Color(color))
|
.set_material_parameter(
|
||||||
|
"color",
|
||||||
|
MaterialParameter::Color(rgba_linear!(0.0, 1.0, 0.0, 1.0)),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.model
|
self.model
|
||||||
.model_part("?????")
|
.model_part("?????")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_material_parameter(
|
.set_material_parameter(
|
||||||
"emission_factor",
|
"emission_factor",
|
||||||
MaterialParameter::Color(color.map(|c| c * 0.75)),
|
MaterialParameter::Color(rgba_linear!(0.0, 0.75, 0.0, 0.75)),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.touch_plane.touch_stopped() {
|
if self.touch_plane.touch_stopped() {
|
||||||
println!("Touch ended");
|
println!("Touch ended");
|
||||||
let color = [1.0, 0.0, 0.0, 1.0];
|
|
||||||
self.model
|
self.model
|
||||||
.model_part("?????")
|
.model_part("?????")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_material_parameter("color", MaterialParameter::Color(color))
|
.set_material_parameter(
|
||||||
|
"color",
|
||||||
|
MaterialParameter::Color(rgba_linear!(1.0, 0.0, 0.0, 1.0)),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.model
|
self.model
|
||||||
.model_part("?????")
|
.model_part("?????")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_material_parameter(
|
.set_material_parameter(
|
||||||
"emission_factor",
|
"emission_factor",
|
||||||
MaterialParameter::Color(color.map(|c| c * 0.5)),
|
MaterialParameter::Color(rgba_linear!(0.5, 0.0, 0.0, 0.5)),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@@ -217,9 +222,10 @@ fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result<Model> {
|
|||||||
t,
|
t,
|
||||||
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
&ResourceID::new_namespaced("protostar", "hexagon/hexagon"),
|
||||||
)?;
|
)?;
|
||||||
model
|
model.model_part("Hex")?.set_material_parameter(
|
||||||
.model_part("Hex")?
|
"color",
|
||||||
.set_material_parameter("color", MaterialParameter::Color([0.0, 1.0, 1.0, 1.0]))?;
|
MaterialParameter::Color(rgba_linear!(0.0, 1.0, 1.0, 1.0)),
|
||||||
|
)?;
|
||||||
model.model_part("Icon")?.set_material_parameter(
|
model.model_part("Icon")?.set_material_parameter(
|
||||||
"diffuse",
|
"diffuse",
|
||||||
MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())),
|
MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())),
|
||||||
@@ -402,12 +408,15 @@ impl App {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
self.grabbable_grow = None;
|
self.grabbable_grow = None;
|
||||||
}
|
}
|
||||||
} else if self.grabbable.valid() && self.grabbable.grab_action().actor_stopped() {
|
} else if self.grabbable.grab_action().actor_stopped() {
|
||||||
self.grabbable_shrink = Some(Tweener::quart_in_out(APP_SIZE * 0.5, 0.0001, 0.25));
|
self.grabbable_shrink = Some(Tweener::quart_in_out(APP_SIZE * 0.5, 0.0001, 0.25));
|
||||||
let Ok(distance_future) = self.grabbable
|
let Ok(distance_future) = self
|
||||||
|
.grabbable
|
||||||
.content_parent()
|
.content_parent()
|
||||||
.get_position_rotation_scale(&self.parent)
|
.get_position_rotation_scale(&self.parent)
|
||||||
else {return};
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let application = self.application.clone();
|
let application = self.application.clone();
|
||||||
let space = self.content_parent().alias();
|
let space = self.content_parent().alias();
|
||||||
|
|||||||
Reference in New Issue
Block a user