angle fade (partial, need monado fix)
This commit is contained in:
@@ -114,6 +114,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div width="100%" padding="8" gap="8" justify_content="center" align_items="center">
|
<div width="100%" padding="8" gap="8" justify_content="center" align_items="center">
|
||||||
<CheckBox id="additive_box" translation="EDIT_MODE.BLENDING_ADDITIVE" tooltip="EDIT_MODE.ALPHA_BLEND_MODE" tooltip_side="bottom" />
|
<CheckBox id="additive_box" translation="EDIT_MODE.BLENDING_ADDITIVE" tooltip="EDIT_MODE.ALPHA_BLEND_MODE" tooltip_side="bottom" />
|
||||||
|
<CheckBox id="angle_fade_box" translation="EDIT_MODE.ANGLE_FADE" tooltip="EDIT_MODE.ANGLE_FADE_HELP" tooltip_side="bottom" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="tab_curve" display="none" height="100" flex_direction="column">
|
<div id="tab_curve" display="none" height="100" flex_direction="column">
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
"ADJUST_CURVATURE": "Adjust curvature",
|
"ADJUST_CURVATURE": "Adjust curvature",
|
||||||
"ALPHA_BLEND_MODE": "Alpha blend mode",
|
"ALPHA_BLEND_MODE": "Alpha blend mode",
|
||||||
"BLENDING_ADDITIVE": "Additive blending",
|
"BLENDING_ADDITIVE": "Additive blending",
|
||||||
|
"ANGLE_FADE": "Angle fade",
|
||||||
|
"ANGLE_FADE_HELP": "Fade when not facing HMD",
|
||||||
"CURVATURE": "Curvature",
|
"CURVATURE": "Curvature",
|
||||||
"DELETE": "Long press to remove from current set",
|
"DELETE": "Long press to remove from current set",
|
||||||
"DISABLE_GRAB": "Disable grab",
|
"DISABLE_GRAB": "Disable grab",
|
||||||
|
|||||||
@@ -30,10 +30,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
config::{save_settings, save_state},
|
config::{save_settings, save_state},
|
||||||
graphics::{GpuFutures, init_openvr_graphics},
|
graphics::{GpuFutures, init_openvr_graphics},
|
||||||
overlays::{
|
overlays::toast::Toast,
|
||||||
toast::Toast,
|
|
||||||
watch::{WATCH_NAME, watch_fade},
|
|
||||||
},
|
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::notifications::NotificationManager,
|
subsystem::notifications::NotificationManager,
|
||||||
windowing::{
|
windowing::{
|
||||||
@@ -134,8 +131,6 @@ pub fn openvr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
|
|||||||
|
|
||||||
log::info!("HMD running @ {refresh_rate} Hz");
|
log::info!("HMD running @ {refresh_rate} Hz");
|
||||||
|
|
||||||
let watch_id = overlays.lookup(WATCH_NAME).unwrap(); // want panic
|
|
||||||
|
|
||||||
// want at least half refresh rate
|
// want at least half refresh rate
|
||||||
let frame_timeout = 2 * (1000.0 / refresh_rate).floor() as u32;
|
let frame_timeout = 2 * (1000.0 / refresh_rate).floor() as u32;
|
||||||
|
|
||||||
@@ -266,11 +261,8 @@ pub fn openvr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
|
|||||||
.enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard));
|
.enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard));
|
||||||
}
|
}
|
||||||
|
|
||||||
overlays
|
overlays.values_mut().for_each(|o| o.config.tick(&mut app));
|
||||||
.values_mut()
|
|
||||||
.for_each(|o| o.config.auto_movement(&mut app));
|
|
||||||
|
|
||||||
watch_fade(&mut app, overlays.mut_by_id(watch_id).unwrap()); // want panic
|
|
||||||
playspace.update(&mut chaperone_mgr, &mut overlays, &app);
|
playspace.update(&mut chaperone_mgr, &mut overlays, &app);
|
||||||
|
|
||||||
current_lines.clear();
|
current_lines.clear();
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> {
|
|||||||
} else {
|
} else {
|
||||||
log::warn!("Missing EXT_composition_layer_equirect2 extension.");
|
log::warn!("Missing EXT_composition_layer_equirect2 extension.");
|
||||||
}
|
}
|
||||||
|
if available_extensions.khr_composition_layer_color_scale_bias {
|
||||||
|
enabled_extensions.khr_composition_layer_color_scale_bias = true;
|
||||||
|
} else {
|
||||||
|
log::warn!("Missing XR_KHR_composition_layer_color_scale_bias extension.");
|
||||||
|
}
|
||||||
|
|
||||||
let xr_mndx_system_buttons = "XR_MNDX_system_buttons".as_bytes().to_vec();
|
let xr_mndx_system_buttons = "XR_MNDX_system_buttons".as_bytes().to_vec();
|
||||||
if available_extensions.other.contains(&xr_mndx_system_buttons) {
|
if available_extensions.other.contains(&xr_mndx_system_buttons) {
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
config::{save_settings, save_state},
|
config::{save_settings, save_state},
|
||||||
graphics::{GpuFutures, init_openxr_graphics},
|
graphics::{GpuFutures, init_openxr_graphics},
|
||||||
overlays::{
|
overlays::{toast::Toast, watch::WATCH_NAME},
|
||||||
toast::Toast,
|
|
||||||
watch::{WATCH_NAME, watch_fade},
|
|
||||||
},
|
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::notifications::NotificationManager,
|
subsystem::notifications::NotificationManager,
|
||||||
windowing::{
|
windowing::{
|
||||||
@@ -289,7 +286,6 @@ pub fn openxr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
|
|||||||
.enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard));
|
.enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard));
|
||||||
}
|
}
|
||||||
|
|
||||||
watch_fade(&mut app, overlays.mut_by_id(watch_id).unwrap()); // want panic
|
|
||||||
if let Some(ref mut space_mover) = playspace {
|
if let Some(ref mut space_mover) = playspace {
|
||||||
space_mover.update(&mut overlays, &mut app);
|
space_mover.update(&mut overlays, &mut app);
|
||||||
}
|
}
|
||||||
@@ -317,9 +313,7 @@ pub fn openxr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
|
|||||||
.submit(&mut app);
|
.submit(&mut app);
|
||||||
}
|
}
|
||||||
|
|
||||||
overlays
|
overlays.values_mut().for_each(|o| o.config.tick(&mut app));
|
||||||
.values_mut()
|
|
||||||
.for_each(|o| o.config.auto_movement(&mut app));
|
|
||||||
|
|
||||||
current_lines.clear();
|
current_lines.clear();
|
||||||
|
|
||||||
@@ -372,6 +366,10 @@ pub fn openxr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
|
|||||||
log::trace!("{}: hidden, skip render", o.config.name);
|
log::trace!("{}: hidden, skip render", o.config.name);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
if alpha < 0.05 {
|
||||||
|
log::trace!("{}: alpha too low, skip render", o.config.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if !o.data.init {
|
if !o.data.init {
|
||||||
log::trace!("{}: init", o.config.name);
|
log::trace!("{}: init", o.config.name);
|
||||||
|
|||||||
@@ -18,6 +18,18 @@ pub struct OpenXrOverlayData {
|
|||||||
pub(super) init: bool,
|
pub(super) init: bool,
|
||||||
pub(super) cur_visible: bool,
|
pub(super) cur_visible: bool,
|
||||||
pub(super) last_alpha: f32,
|
pub(super) last_alpha: f32,
|
||||||
|
color_bias_khr: Option<Box<xr::sys::CompositionLayerColorScaleBiasKHR>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! next_chain_insert {
|
||||||
|
($layer:expr, $payload:expr) => {{
|
||||||
|
let payload_ptr = $payload.as_mut() as *mut _ as *mut xr::sys::BaseInStructure;
|
||||||
|
let new_elem = payload_ptr.as_mut().unwrap();
|
||||||
|
let mut raw = $layer.into_raw();
|
||||||
|
new_elem.next = raw.next as _;
|
||||||
|
raw.next = payload_ptr as *const _;
|
||||||
|
raw
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OverlayWindowData<OpenXrOverlayData> {
|
impl OverlayWindowData<OpenXrOverlayData> {
|
||||||
@@ -110,8 +122,10 @@ impl OverlayWindowData<OpenXrOverlayData> {
|
|||||||
let posef = helpers::translation_rotation_to_posef(center_point, quat);
|
let posef = helpers::translation_rotation_to_posef(center_point, quat);
|
||||||
let angle = 2.0 * (scale_x / (2.0 * radius));
|
let angle = 2.0 * (scale_x / (2.0 * radius));
|
||||||
|
|
||||||
|
try_update_color_scale_bias(xr, &mut self.data.color_bias_khr, state.alpha);
|
||||||
|
|
||||||
for sub_image in sub_images {
|
for sub_image in sub_images {
|
||||||
let cylinder = xr::CompositionLayerCylinderKHR::new()
|
let mut cylinder = xr::CompositionLayerCylinderKHR::new()
|
||||||
.layer_flags(flags)
|
.layer_flags(flags)
|
||||||
.pose(posef)
|
.pose(posef)
|
||||||
.sub_image(sub_image.0)
|
.sub_image(sub_image.0)
|
||||||
@@ -120,12 +134,22 @@ impl OverlayWindowData<OpenXrOverlayData> {
|
|||||||
.radius(radius)
|
.radius(radius)
|
||||||
.central_angle(angle)
|
.central_angle(angle)
|
||||||
.aspect_ratio(aspect_ratio);
|
.aspect_ratio(aspect_ratio);
|
||||||
|
|
||||||
|
if let Some(color_bias_khr) = self.data.color_bias_khr.as_mut() {
|
||||||
|
unsafe {
|
||||||
|
let raw = next_chain_insert!(cylinder, color_bias_khr);
|
||||||
|
cylinder = xr::CompositionLayerCylinderKHR::from_raw(raw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
layers.push(CompositionLayer::Cylinder(cylinder));
|
layers.push(CompositionLayer::Cylinder(cylinder));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let posef = helpers::transform_to_posef(&transform);
|
let posef = helpers::transform_to_posef(&transform);
|
||||||
|
try_update_color_scale_bias(xr, &mut self.data.color_bias_khr, state.alpha);
|
||||||
|
|
||||||
for sub_image in sub_images {
|
for sub_image in sub_images {
|
||||||
let quad = xr::CompositionLayerQuad::new()
|
let mut quad = xr::CompositionLayerQuad::new()
|
||||||
.layer_flags(flags)
|
.layer_flags(flags)
|
||||||
.pose(posef)
|
.pose(posef)
|
||||||
.sub_image(sub_image.0)
|
.sub_image(sub_image.0)
|
||||||
@@ -135,6 +159,14 @@ impl OverlayWindowData<OpenXrOverlayData> {
|
|||||||
width: scale_x,
|
width: scale_x,
|
||||||
height: scale_y,
|
height: scale_y,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if let Some(color_bias_khr) = self.data.color_bias_khr.as_mut() {
|
||||||
|
unsafe {
|
||||||
|
let raw = next_chain_insert!(quad, color_bias_khr);
|
||||||
|
quad = xr::CompositionLayerQuad::from_raw(raw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
layers.push(CompositionLayer::Quad(quad));
|
layers.push(CompositionLayer::Quad(quad));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,3 +191,33 @@ impl OverlayWindowData<OpenXrOverlayData> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_update_color_scale_bias(
|
||||||
|
xr_state: &XrState,
|
||||||
|
color_bias_khr: &mut Option<Box<xr::sys::CompositionLayerColorScaleBiasKHR>>,
|
||||||
|
alpha: f32,
|
||||||
|
) {
|
||||||
|
if let Some(item) = color_bias_khr.as_mut() {
|
||||||
|
item.color_scale.a = alpha;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if xr_state
|
||||||
|
.instance
|
||||||
|
.exts()
|
||||||
|
.khr_composition_layer_color_scale_bias
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let new_item = Box::new(xr::sys::CompositionLayerColorScaleBiasKHR {
|
||||||
|
ty: xr::StructureType::COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR,
|
||||||
|
next: std::ptr::null(),
|
||||||
|
color_bias: Default::default(),
|
||||||
|
color_scale: xr::Color4f {
|
||||||
|
a: alpha,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
});
|
||||||
|
*color_bias_khr = Some(new_item);
|
||||||
|
}
|
||||||
|
|||||||
@@ -432,6 +432,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
|||||||
set_up_checkbox(&mut panel, "additive_box", cb_assign_additive)?;
|
set_up_checkbox(&mut panel, "additive_box", cb_assign_additive)?;
|
||||||
set_up_checkbox(&mut panel, "align_box", cb_assign_align)?;
|
set_up_checkbox(&mut panel, "align_box", cb_assign_align)?;
|
||||||
set_up_checkbox(&mut panel, "global_box", cb_assign_global)?;
|
set_up_checkbox(&mut panel, "global_box", cb_assign_global)?;
|
||||||
|
set_up_checkbox(&mut panel, "angle_fade_box", cb_assign_angle_fade)?;
|
||||||
set_up_checkbox(&mut panel, "block_input_box", cb_assign_block_input)?;
|
set_up_checkbox(&mut panel, "block_input_box", cb_assign_block_input)?;
|
||||||
set_up_checkbox(
|
set_up_checkbox(
|
||||||
&mut panel,
|
&mut panel,
|
||||||
@@ -499,6 +500,11 @@ fn reset_panel(
|
|||||||
.fetch_component_as::<ComponentCheckbox>("global_box")?;
|
.fetch_component_as::<ComponentCheckbox>("global_box")?;
|
||||||
c.set_checked(&mut common, owc.global);
|
c.set_checked(&mut common, owc.global);
|
||||||
|
|
||||||
|
let c = panel
|
||||||
|
.parser_state
|
||||||
|
.fetch_component_as::<ComponentCheckbox>("angle_fade_box")?;
|
||||||
|
c.set_checked(&mut common, state.angle_fade);
|
||||||
|
|
||||||
let c = panel
|
let c = panel
|
||||||
.parser_state
|
.parser_state
|
||||||
.fetch_component_as::<ComponentCheckbox>("block_input_box")?;
|
.fetch_component_as::<ComponentCheckbox>("block_input_box")?;
|
||||||
@@ -607,6 +613,14 @@ const fn cb_assign_global(_app: &mut AppState, owc: &mut OverlayWindowConfig, gl
|
|||||||
owc.global = global;
|
owc.global = global;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fn cb_assign_angle_fade(
|
||||||
|
_app: &mut AppState,
|
||||||
|
owc: &mut OverlayWindowConfig,
|
||||||
|
angle_fade: bool,
|
||||||
|
) {
|
||||||
|
owc.active_state.as_mut().unwrap().angle_fade = angle_fade;
|
||||||
|
}
|
||||||
|
|
||||||
const fn cb_assign_block_input(
|
const fn cb_assign_block_input(
|
||||||
_app: &mut AppState,
|
_app: &mut AppState,
|
||||||
owc: &mut OverlayWindowConfig,
|
owc: &mut OverlayWindowConfig,
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
|||||||
WATCH_ROT,
|
WATCH_ROT,
|
||||||
WATCH_POS,
|
WATCH_POS,
|
||||||
),
|
),
|
||||||
|
angle_fade: true,
|
||||||
..OverlayWindowState::default()
|
..OverlayWindowState::default()
|
||||||
},
|
},
|
||||||
show_on_spawn: true,
|
show_on_spawn: true,
|
||||||
@@ -213,18 +214,3 @@ fn sets_or_overlays(
|
|||||||
alterables.set_style(widget[i], StyleSetRequest::Display(display[i]));
|
alterables.set_style(widget[i], StyleSetRequest::Display(display[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ impl OscSender {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// skip overlays that are fully transparent; e.g. the watch when not looking at it
|
// skip overlays that are fully transparent; e.g. the watch when not looking at it
|
||||||
if state.alpha <= 0f32 {
|
if state.alpha <= 0.05 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use wlx_common::{
|
|||||||
astr_containers::{AStrMap, AStrMapExt},
|
astr_containers::{AStrMap, AStrMapExt},
|
||||||
config::SerializedWindowSet,
|
config::SerializedWindowSet,
|
||||||
overlays::{BackendAttrib, BackendAttribValue, ToastTopic},
|
overlays::{BackendAttrib, BackendAttribValue, ToastTopic},
|
||||||
|
windowing::Positioning,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -26,7 +27,7 @@ use crate::{
|
|||||||
keyboard::create_keyboard,
|
keyboard::create_keyboard,
|
||||||
screen::create_screens,
|
screen::create_screens,
|
||||||
toast::Toast,
|
toast::Toast,
|
||||||
watch::create_watch,
|
watch::{WATCH_NAME, create_watch},
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
windowing::{
|
windowing::{
|
||||||
@@ -44,6 +45,7 @@ pub struct OverlayWindowManager<T> {
|
|||||||
wrappers: EditWrapperManager,
|
wrappers: EditWrapperManager,
|
||||||
overlays: HopSlotMap<OverlayID, OverlayWindowData<T>>,
|
overlays: HopSlotMap<OverlayID, OverlayWindowData<T>>,
|
||||||
sets: Vec<OverlayWindowSet>,
|
sets: Vec<OverlayWindowSet>,
|
||||||
|
global_set: OverlayWindowSet,
|
||||||
/// The set that is currently visible.
|
/// The set that is currently visible.
|
||||||
current_set: Option<usize>,
|
current_set: Option<usize>,
|
||||||
/// The set that will be restored by show_hide.
|
/// The set that will be restored by show_hide.
|
||||||
@@ -68,6 +70,7 @@ where
|
|||||||
current_set: Some(0),
|
current_set: Some(0),
|
||||||
restore_set: 0,
|
restore_set: 0,
|
||||||
sets: vec![OverlayWindowSet::default()],
|
sets: vec![OverlayWindowSet::default()],
|
||||||
|
global_set: OverlayWindowSet::default(),
|
||||||
anchor_local: Affine3A::from_translation(Vec3::NEG_Z),
|
anchor_local: Affine3A::from_translation(Vec3::NEG_Z),
|
||||||
watch_id: OverlayID::null(), // set down below
|
watch_id: OverlayID::null(), // set down below
|
||||||
keyboard_id: OverlayID::null(), // set down below
|
keyboard_id: OverlayID::null(), // set down below
|
||||||
@@ -195,16 +198,19 @@ where
|
|||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let parent_set = if o.config.global {
|
||||||
|
&mut self.global_set
|
||||||
|
} else {
|
||||||
|
&mut self.sets[self.restore_set]
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(active_state) = o.config.active_state.take() {
|
if let Some(active_state) = o.config.active_state.take() {
|
||||||
log::debug!("{}: toggle off", o.config.name);
|
log::debug!("{}: toggle off", o.config.name);
|
||||||
|
|
||||||
self.sets[self.restore_set]
|
parent_set
|
||||||
.hidden_overlays
|
.hidden_overlays
|
||||||
.arc_set(o.config.name.clone(), active_state);
|
.arc_set(o.config.name.clone(), active_state);
|
||||||
} else if let Some(state) = self.sets[self.restore_set]
|
} else if let Some(state) = parent_set.hidden_overlays.arc_rm(&o.config.name) {
|
||||||
.hidden_overlays
|
|
||||||
.arc_rm(&o.config.name)
|
|
||||||
{
|
|
||||||
let o = &mut self.overlays[id];
|
let o = &mut self.overlays[id];
|
||||||
log::debug!("{}: toggle on", o.config.name);
|
log::debug!("{}: toggle on", o.config.name);
|
||||||
o.config.dirty = true;
|
o.config.dirty = true;
|
||||||
@@ -509,15 +515,32 @@ impl<T> OverlayWindowManager<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// global overlays
|
// global overlays
|
||||||
for oid in &[self.watch_id] {
|
for (name, ows) in app.session.config.global_set.clone().into_iter() {
|
||||||
if let Some(o) = self.mut_by_id(*oid) {
|
let mut ows = ows.clone();
|
||||||
if let Some(state) = app.session.config.global_set.get(&*o.config.name).cloned() {
|
|
||||||
o.config.active_state = Some(state);
|
// fix angle_fade missing on watch if loading older state
|
||||||
o.config.reset(app, false);
|
if name.as_ref() == WATCH_NAME {
|
||||||
log::debug!("global set: loaded state for {}", o.config.name);
|
ows.angle_fade = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(oid) = self.lookup(&*name)
|
||||||
|
&& let Some(o) = self.mut_by_id(oid)
|
||||||
|
{
|
||||||
|
o.config.global = true;
|
||||||
|
if o.config.active_state.is_none() {
|
||||||
|
self.global_set.hidden_overlays.arc_set(name.clone(), ows);
|
||||||
} else {
|
} else {
|
||||||
log::debug!("global set: no state for {}", o.config.name);
|
o.config.active_state = Some(ows);
|
||||||
|
o.config.reset(app, false);
|
||||||
}
|
}
|
||||||
|
log::debug!("global set: loaded state for {name}");
|
||||||
|
} else {
|
||||||
|
log::debug!(
|
||||||
|
"global set has saved state for {name} which doesn't exist. will apply state once added."
|
||||||
|
);
|
||||||
|
self.global_set
|
||||||
|
.inactive_overlays
|
||||||
|
.arc_set(name.clone(), ows.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,12 @@ impl OverlayWindowConfig {
|
|||||||
self.active_state = None;
|
self.active_state = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn auto_movement(&mut self, app: &mut AppState) {
|
pub fn tick(&mut self, app: &mut AppState) {
|
||||||
|
self.auto_movement(app);
|
||||||
|
self.angle_fade(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn auto_movement(&mut self, app: &mut AppState) {
|
||||||
if self.pause_movement {
|
if self.pause_movement {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -188,6 +193,25 @@ impl OverlayWindowConfig {
|
|||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn angle_fade(&mut self, app: &mut AppState) {
|
||||||
|
let Some(state) = self.active_state.as_mut() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if !state.angle_fade {
|
||||||
|
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.);
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if changes were saved.
|
/// Returns true if changes were saved.
|
||||||
pub fn reset(&mut self, app: &mut AppState, hard_reset: bool) {
|
pub fn reset(&mut self, app: &mut AppState, hard_reset: bool) {
|
||||||
let Some(state) = self.active_state.as_mut() else {
|
let Some(state) = self.active_state.as_mut() else {
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ pub struct OverlayWindowState {
|
|||||||
pub additive: bool,
|
pub additive: bool,
|
||||||
pub saved_transform: Option<Affine3A>,
|
pub saved_transform: Option<Affine3A>,
|
||||||
pub block_input: bool,
|
pub block_input: bool,
|
||||||
|
pub angle_fade: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for OverlayWindowState {
|
impl Default for OverlayWindowState {
|
||||||
@@ -91,6 +92,7 @@ impl Default for OverlayWindowState {
|
|||||||
additive: false,
|
additive: false,
|
||||||
saved_transform: None,
|
saved_transform: None,
|
||||||
block_input: true,
|
block_input: true,
|
||||||
|
angle_fade: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user