wayvr/wlx-overlay-s/src/overlays/watch.rs

93 lines
2.9 KiB
Rust

use std::{collections::HashMap, rc::Rc, time::Duration};
use glam::{Affine3A, Vec3, Vec3A};
use crate::{
gui::{
panel::{GuiPanel, NewGuiPanelParams},
timer::GuiTimer,
},
state::AppState,
windowing::{
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState, Positioning},
Z_ORDER_WATCH,
},
};
pub const WATCH_NAME: &str = "watch";
struct WatchState {}
#[allow(clippy::significant_drop_tightening)]
pub fn create_watch(app: &mut AppState, num_sets: usize) -> anyhow::Result<OverlayWindowConfig> {
let state = WatchState {};
let mut panel = GuiPanel::new_from_template(
app,
"gui/watch.xml",
state,
NewGuiPanelParams {
on_custom_id: Some(Box::new(
move |id, widget, doc_params, layout, parser_state| {
if &*id != "sets" {
return Ok(());
}
for idx in 0..num_sets {
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert("display".into(), (idx + 1).to_string().into());
params.insert("handle".into(), idx.to_string().into());
parser_state
.instantiate_template(doc_params, "Set", layout, widget, params)?;
}
Ok(())
},
)),
..Default::default()
},
)?;
panel
.timers
.push(GuiTimer::new(Duration::from_millis(100), 0));
let positioning = Positioning::FollowHand {
hand: app.session.config.watch_hand,
lerp: 1.0,
};
panel.update_layout()?;
Ok(OverlayWindowConfig {
name: WATCH_NAME.into(),
z_order: Z_ORDER_WATCH,
default_state: OverlayWindowState {
interactable: true,
positioning,
transform: Affine3A::from_scale_rotation_translation(
Vec3::ONE * 0.115,
app.session.config.watch_rot,
app.session.config.watch_pos,
),
..OverlayWindowState::default()
},
show_on_spawn: true,
global: true,
..OverlayWindowConfig::from_backend(Box::new(panel))
})
}
pub fn watch_fade<D>(app: &mut AppState, watch: &mut OverlayWindowData<D>) {
let Some(state) = watch.config.active_state.as_mut() else {
return;
};
let to_hmd = (state.transform.translation - app.input_state.hmd.translation).normalize();
let watch_normal = state.transform.transform_vector3a(Vec3A::NEG_Z).normalize();
let dot = to_hmd.dot(watch_normal);
state.alpha = (dot - app.session.config.watch_view_angle_min)
/ (app.session.config.watch_view_angle_max - app.session.config.watch_view_angle_min);
state.alpha += 0.1;
state.alpha = state.alpha.clamp(0., 1.);
}