mirror of https://github.com/wayvr-org/wayvr.git
Merge branch 'main' into fix/glyph-upload
This commit is contained in:
commit
aa07e98802
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="currentColor" d="m12 22l-4.25-4.25l1.425-1.425L11 18.15V13H5.875L7.7 14.8l-1.45 1.45L2 12l4.225-4.225L7.65 9.2L5.85 11H11V5.85L9.175 7.675L7.75 6.25L12 2l4.25 4.25l-1.425 1.425L13 5.85V11h5.125L16.3 9.2l1.45-1.45L22 12l-4.25 4.25l-1.425-1.425L18.15 13H13v5.125l1.8-1.825l1.45 1.45z"/></svg>
|
||||
|
After Width: | Height: | Size: 500 B |
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="gravity.svg"
|
||||
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="23.234375"
|
||||
inkscape:cx="17.861466"
|
||||
inkscape:cy="22.488231"
|
||||
inkscape:window-width="1582"
|
||||
inkscape:window-height="1302"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg1" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
|
||||
<!-- Modified it a little bit, there's no "space gravity" icon available. -->
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="m 15.76786,18.274928 -1.391472,0.295932 -0.674684,-2.9751 -3.051267,-0.735557 -2.4062791,-3.292082 -0.8846145,1.824345 1.561484,2.213127 -1.1706157,0.808349 -1.9932655,-2.862487 1.752944,-3.7745856 Q 7.740355,9.2978686 8.2693798,9.1366908 8.7984057,8.9755132 9.3446883,8.9671549 9.9537305,8.9704882 10.547911,8.8283107 11.142091,8.6861403 11.667399,8.364791 12.192707,8.0434408 12.541821,7.5511898 12.890935,7.0589389 13.170167,6.5208564 l 1.228561,0.6477209 q -0.321651,0.575352 -0.696034,1.1164692 -0.374382,0.5411172 -0.890945,0.9726251 -0.466314,0.3718768 -0.998843,0.6112737 -0.532529,0.2393967 -1.117089,0.3386867 L 12,12 l 2.176682,-1.469824 4.352172,0.934365 -0.326914,1.35612 -3.582453,-0.734464 -2.11263,1.442217 2.281549,0.535655 z M 7.5517982,8.9044443 Q 7.0233673,9.1322023 6.4853273,8.9182692 5.9472884,8.7043353 5.7186139,8.1755407 5.4899403,7.6467461 5.7054294,7.108795 5.9209195,6.5708439 6.4475175,6.3423563 6.9741154,6.1138698 7.5149037,6.3288971 8.0556931,6.5439235 8.2807018,7.07126 8.5057095,7.5985974 8.2948017,8.1383704 8.0838948,8.6781445 7.5517982,8.9044443"
|
||||
id="path1"
|
||||
style="stroke-width:0.697484" />
|
||||
<path
|
||||
id="path2"
|
||||
style="fill:none;stroke:currentColor;stroke-width:2.43525;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:0, 7.30575"
|
||||
d="M 22.480952,12 C 22.480952,17.78847 17.78847,22.480952 12,22.480952 6.2115299,22.480952 1.5190477,17.78847 1.5190477,12 1.5190475,6.2115298 6.2115298,1.5190477 12,1.5190477 c 0.653263,0 1.292568,0.059766 1.912744,0.1741274 C 18.787854,2.5921561 22.480952,6.8647934 22.480952,12 Z"
|
||||
sodipodi:nodetypes="ssssss" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
|
|
@ -13,13 +13,13 @@
|
|||
</template>
|
||||
|
||||
<template name="SliderSetting">
|
||||
<label text="${text}" translation="${translation}" />
|
||||
<Slider id="${id}" width="250" height="24" min_value="${min}" max_value="${max}" step="${step}" value="${value}" tooltip="${tooltip}" />
|
||||
<Slider id="${id}" width="200" height="24" min_value="${min}" max_value="${max}" step="${step}" value="${value}" tooltip="${tooltip}" />
|
||||
<label text="${text}" weight="bold" translation="${translation}" />
|
||||
</template>
|
||||
|
||||
<template name="RangeSetting">
|
||||
<label text="${text}" translation="${translation}" />
|
||||
<Slider id="${id}" width="250" height="24" min_value="${min}" max_value="${max}" step="${step}" value="${value}" value2="${value2}" tooltip="${tooltip}" />
|
||||
<Slider id="${id}" width="200" height="24" min_value="${min}" max_value="${max}" step="${step}" value="${value}" value2="${value2}" tooltip="${tooltip}" />
|
||||
<label text="${text}" weight="bold" translation="${translation}" />
|
||||
</template>
|
||||
|
||||
<template name="SelectSetting">
|
||||
|
|
@ -56,6 +56,7 @@
|
|||
<Tab name="skybox" translation="APP_SETTINGS.SKYBOX" sprite_src_builtin="dashboard/globe.svg" />
|
||||
<Tab name="features" translation="APP_SETTINGS.FEATURES" sprite_src_builtin="dashboard/options.svg" />
|
||||
<Tab name="controls" translation="APP_SETTINGS.CONTROLS" sprite_src_builtin="dashboard/controller.svg" />
|
||||
<Tab name="space_drag" translation="APP_SETTINGS.SPACE_DRAG" sprite_src_builtin="dashboard/drag.svg" />
|
||||
<Tab name="misc" translation="APP_SETTINGS.MISC" sprite_src_builtin="dashboard/blocks.svg" />
|
||||
<Tab name="autostart_apps" translation="APP_SETTINGS.AUTOSTART_APPS" sprite_src_builtin="dashboard/apps.svg" />
|
||||
<Tab name="troubleshooting" translation="APP_SETTINGS.TROUBLESHOOTING" sprite_src_builtin="dashboard/cpu.svg" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
|
||||
<elements>
|
||||
<div id="common_options_parent" flex_direction="column" gap="8"/>
|
||||
<rectangle macro="group_box">
|
||||
<GroupBoxTitle src_builtin="dashboard/gravity.svg" translation="APP_SETTINGS.SPACE_GRAVITY_GRAVITY" />
|
||||
<div id="gravity_enabled_parent"/>
|
||||
<div id="space_gravity_parent" flex_direction="column" gap="8">
|
||||
<!-- filled-in at runtime -->
|
||||
</div>
|
||||
</rectangle>
|
||||
</elements>
|
||||
</layout>
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
"DELETE_ALL_CONFIGS_HELP": "Remove all configuration files from conf.d",
|
||||
"DOUBLE_CURSOR_FIX": "Double cursor fix",
|
||||
"DOUBLE_CURSOR_FIX_HELP": "Enable this if you see 2 cursors",
|
||||
"ENABLED": "Enabled",
|
||||
"FEATURES": "Features",
|
||||
"FOCUS_FOLLOWS_MOUSE_MODE": "Mouse move on trigger touch",
|
||||
"HANDSFREE_POINTER": "Handsfree mode",
|
||||
|
|
@ -72,9 +73,10 @@
|
|||
"LONG_PRESS_DURATION": "Long press duration",
|
||||
"LOOK_AND_FEEL": "Look & Feel",
|
||||
"MISC": "Miscellaneous",
|
||||
"NO_SKYMAPS_FOUND": "No skymaps found",
|
||||
"NOTIFICATIONS_ENABLED": "Enable notifications",
|
||||
"NOTIFICATIONS_SOUND_ENABLED": "Notification sounds",
|
||||
"NOT_SUPPORTED": "Not supported",
|
||||
"NO_SKYMAPS_FOUND": "No skymaps found",
|
||||
"OPAQUE_BACKGROUND": "Opaque background",
|
||||
"OPTION": {
|
||||
"AUTO": "Automatic",
|
||||
|
|
@ -100,11 +102,23 @@
|
|||
"SCREEN_RENDER_DOWN_HELP": "Helps with aliasing on high-res screens",
|
||||
"SCROLL_SPEED": "Scroll speed",
|
||||
"SELECT_VARIANT": "Select variant",
|
||||
"ENABLE_WATCH": "Enable watch",
|
||||
"SETS_ON_WATCH": "Sets on watch",
|
||||
"SKYBOX": "Skybox",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",
|
||||
"SPACE_DRAG": "Space drag",
|
||||
"SPACE_DRAG_MULTIPLIER": "Space drag multiplier",
|
||||
"SPACE_DRAG_UNLOCKED": "Allow space drag on all axes",
|
||||
"SPACE_GRAVITY_DAMPING": "Damping",
|
||||
"SPACE_GRAVITY_DAMPING_HELP": "Artificial drag to slow down movement. 0.1 - high drag, 1.0 - no drag",
|
||||
"SPACE_GRAVITY_FLING_STRENGTH": "Fling strength",
|
||||
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Intensity multiplier of gravitational launch force after space-drag.\n0.0 - no movement at all, 2.0 - double intensity",
|
||||
"SPACE_GRAVITY_GRAVITY": "Gravity",
|
||||
"SPACE_GRAVITY_GRAVITY_HELP": "Amount of downwards force. 0.0 - no gravity",
|
||||
"SPACE_GRAVITY_GROUND_FRICTION": "Ground friction",
|
||||
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Amount of friction slowing you down if you're touching the ground.\n0.0 - no friction (just like on ice), 1.0 - rough surface",
|
||||
"SPACE_GRAVITY_FLOOR_HEIGHT": "Floor height",
|
||||
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "The Y position where the floor is. Gravity stops when you reach this height.",
|
||||
"SPACE_ROTATE_UNLOCKED": "Allow space rotate on all axes",
|
||||
"TROUBLESHOOTING": "Troubleshooting",
|
||||
"UI_GRADIENT_INTENSITY": "UI Gradient intensity",
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
"USE_SKYBOX_HELP": "Wyświetlaj niebo, jeśli nie ma aplikacji sceny lub passthrough",
|
||||
"USE_PASSTHROUGH_HELP": "Pozwól na passthrough, jeśli runtime XR to obsługuje",
|
||||
"SCREEN_RENDER_DOWN_HELP": "Pomaga redukować aliasing na ekranach o wysokiej rozdzielczości",
|
||||
"ENABLE_WATCH": "Włącz zegarek",
|
||||
"SETS_ON_WATCH": "Lista zestawów na zegarku",
|
||||
"TROUBLESHOOTING": "Rozwiązywanie problemów",
|
||||
"CLEAR_SAVED_STATE": "Wyczyść zapisany stan",
|
||||
|
|
|
|||
|
|
@ -295,8 +295,8 @@ impl AppList {
|
|||
state: &Rc<RefCell<State>>,
|
||||
parser_state: &mut ParserState,
|
||||
) -> anyhow::Result<()> {
|
||||
// load 4 entries for a single frame at most
|
||||
for _ in 0..4 {
|
||||
// load 30 entries for a single frame at most
|
||||
for _ in 0..30 {
|
||||
if let Some(entry) = self.entries_to_mount.pop_front() {
|
||||
let globals = frontend.layout.state.globals.clone();
|
||||
let button = self.mount_entry(frontend, parser_state, &doc_params(globals.clone()), &entry)?;
|
||||
|
|
|
|||
|
|
@ -39,29 +39,32 @@ mod tab_features;
|
|||
mod tab_look_and_feel;
|
||||
mod tab_misc;
|
||||
mod tab_skybox;
|
||||
mod tab_space_drag;
|
||||
mod tab_troubleshooting;
|
||||
|
||||
#[derive(Clone)]
|
||||
enum TabNameEnum {
|
||||
LookAndFeel,
|
||||
Features,
|
||||
Controls,
|
||||
Misc,
|
||||
AutostartApps,
|
||||
Troubleshooting,
|
||||
Controls,
|
||||
Features,
|
||||
LookAndFeel,
|
||||
Misc,
|
||||
Skybox,
|
||||
SpaceDrag,
|
||||
Troubleshooting,
|
||||
}
|
||||
|
||||
impl TabNameEnum {
|
||||
fn from_string(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
"look_and_feel" => Some(TabNameEnum::LookAndFeel),
|
||||
"features" => Some(TabNameEnum::Features),
|
||||
"controls" => Some(TabNameEnum::Controls),
|
||||
"misc" => Some(TabNameEnum::Misc),
|
||||
"autostart_apps" => Some(TabNameEnum::AutostartApps),
|
||||
"troubleshooting" => Some(TabNameEnum::Troubleshooting),
|
||||
"controls" => Some(TabNameEnum::Controls),
|
||||
"features" => Some(TabNameEnum::Features),
|
||||
"look_and_feel" => Some(TabNameEnum::LookAndFeel),
|
||||
"misc" => Some(TabNameEnum::Misc),
|
||||
"skybox" => Some(TabNameEnum::Skybox),
|
||||
"space_drag" => Some(TabNameEnum::SpaceDrag),
|
||||
"troubleshooting" => Some(TabNameEnum::Troubleshooting),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -69,18 +72,18 @@ impl TabNameEnum {
|
|||
|
||||
#[derive(Clone)]
|
||||
enum Task {
|
||||
UpdateBool(SettingType, bool),
|
||||
UpdateFloat(SettingType, f32),
|
||||
UpdateInt(SettingType, i32),
|
||||
SettingUpdated(SettingType),
|
||||
OpenContextMenu(Vec2, Vec<context_menu::Cell>),
|
||||
ClearPipewireTokens,
|
||||
ClearSavedState,
|
||||
DeleteAllConfigs,
|
||||
OpenContextMenu(Vec2, Vec<context_menu::Cell>),
|
||||
RemoveAutostartApp(Rc<str>),
|
||||
ResetPlayspace,
|
||||
RestartSoftware,
|
||||
RemoveAutostartApp(Rc<str>),
|
||||
SetTab(TabNameEnum),
|
||||
SettingUpdated(SettingType),
|
||||
UpdateBool(SettingType, bool),
|
||||
UpdateFloat(SettingType, f32),
|
||||
UpdateInt(SettingType, i32),
|
||||
}
|
||||
|
||||
struct SettingsMountParams<'a> {
|
||||
|
|
@ -90,10 +93,20 @@ struct SettingsMountParams<'a> {
|
|||
feats: InterfaceFeats,
|
||||
}
|
||||
|
||||
struct SettingUpdatedParams<'a> {
|
||||
layout: &'a mut Layout,
|
||||
config: &'a GeneralConfig,
|
||||
setting_type: SettingType,
|
||||
}
|
||||
|
||||
trait SettingsTab {
|
||||
fn update(&mut self, _par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setting_updated(&mut self, _sup: &mut SettingUpdatedParams) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TabSettings<T> {
|
||||
|
|
@ -203,12 +216,21 @@ impl<T> Tab<T> for TabSettings<T> {
|
|||
changed = Some(ConfigChangeKind::OverlayConfig);
|
||||
}
|
||||
}
|
||||
Task::SettingUpdated(setting) => match setting {
|
||||
SettingType::UiAnimationSpeed | SettingType::UiGradientIntensity | SettingType::UiRoundMultiplier => {
|
||||
// todo: currently, wayvr restart is required to apply these changes (WguiTheme is Rc)
|
||||
Task::SettingUpdated(setting) => {
|
||||
if let Some(tab) = &mut self.current_tab {
|
||||
tab.setting_updated(&mut SettingUpdatedParams {
|
||||
layout: &mut frontend.layout,
|
||||
config: frontend.interface.general_config(data),
|
||||
setting_type: setting,
|
||||
})?;
|
||||
}
|
||||
_ => { /* do nothing */ }
|
||||
},
|
||||
match setting {
|
||||
SettingType::UiAnimationSpeed | SettingType::UiGradientIntensity | SettingType::UiRoundMultiplier => {
|
||||
// todo: currently, wayvr restart is required to apply these changes (WguiTheme is Rc)
|
||||
}
|
||||
_ => { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,7 +269,7 @@ impl<T> Tab<T> for TabSettings<T> {
|
|||
|
||||
// Sorted alphabetically
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[derive(Clone, Copy, AsRefStr, EnumString)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, AsRefStr, EnumString)]
|
||||
enum SettingType {
|
||||
AllowSliding,
|
||||
BlockGameInput,
|
||||
|
|
@ -258,6 +280,7 @@ enum SettingType {
|
|||
Clock12h,
|
||||
DoubleCursorFix,
|
||||
FocusFollowsMouseMode,
|
||||
GridOpacity,
|
||||
HandsfreePointer,
|
||||
HideGrabHelp,
|
||||
HideUsername,
|
||||
|
|
@ -274,9 +297,16 @@ enum SettingType {
|
|||
PointerLerpFactor,
|
||||
ScreenRenderDown,
|
||||
ScrollSpeed,
|
||||
EnableWatch,
|
||||
SetsOnWatch,
|
||||
SpaceDragMultiplier,
|
||||
SpaceDragUnlocked,
|
||||
SpaceGravityDamping,
|
||||
SpaceGravityEnabled,
|
||||
SpaceGravityFlingStrength,
|
||||
SpaceGravityGravity,
|
||||
SpaceGravityGroundFriction,
|
||||
SpaceGravityFloorHeight,
|
||||
SpaceRotateUnlocked,
|
||||
UiAnimationSpeed,
|
||||
UiGradientIntensity,
|
||||
|
|
@ -284,7 +314,6 @@ enum SettingType {
|
|||
UprightScreenFix,
|
||||
UsePassthrough,
|
||||
UseSkybox,
|
||||
GridOpacity,
|
||||
WatchViewAngleMax,
|
||||
WatchViewAngleMin,
|
||||
XrClickSensitivity,
|
||||
|
|
@ -302,29 +331,31 @@ impl SettingType {
|
|||
|
||||
pub fn mut_bool(self, config: &mut GeneralConfig) -> &mut bool {
|
||||
match self {
|
||||
Self::InvertScrollDirectionX => &mut config.invert_scroll_direction_x,
|
||||
Self::InvertScrollDirectionY => &mut config.invert_scroll_direction_y,
|
||||
Self::NotificationsEnabled => &mut config.notifications_enabled,
|
||||
Self::NotificationsSoundEnabled => &mut config.notifications_sound_enabled,
|
||||
Self::KeyboardSoundEnabled => &mut config.keyboard_sound_enabled,
|
||||
Self::UprightScreenFix => &mut config.upright_screen_fix,
|
||||
Self::DoubleCursorFix => &mut config.double_cursor_fix,
|
||||
Self::SetsOnWatch => &mut config.sets_on_watch,
|
||||
Self::HideGrabHelp => &mut config.hide_grab_help,
|
||||
Self::AllowSliding => &mut config.allow_sliding,
|
||||
Self::FocusFollowsMouseMode => &mut config.focus_follows_mouse_mode,
|
||||
Self::LeftHandedMouse => &mut config.left_handed_mouse,
|
||||
Self::BlockGameInput => &mut config.block_game_input,
|
||||
Self::BlockGameInputIgnoreWatch => &mut config.block_game_input_ignore_watch,
|
||||
Self::BlockPosesOnKbdInteraction => &mut config.block_poses_on_kbd_interaction,
|
||||
Self::UseSkybox => &mut config.use_skybox,
|
||||
Self::UsePassthrough => &mut config.use_passthrough,
|
||||
Self::ScreenRenderDown => &mut config.screen_render_down,
|
||||
Self::SpaceDragUnlocked => &mut config.space_drag_unlocked,
|
||||
Self::SpaceRotateUnlocked => &mut config.space_rotate_unlocked,
|
||||
Self::Clock12h => &mut config.clock_12h,
|
||||
Self::DoubleCursorFix => &mut config.double_cursor_fix,
|
||||
Self::EnableWatch => &mut config.enable_watch,
|
||||
Self::FocusFollowsMouseMode => &mut config.focus_follows_mouse_mode,
|
||||
Self::HideGrabHelp => &mut config.hide_grab_help,
|
||||
Self::HideUsername => &mut config.hide_username,
|
||||
Self::InvertScrollDirectionX => &mut config.invert_scroll_direction_x,
|
||||
Self::InvertScrollDirectionY => &mut config.invert_scroll_direction_y,
|
||||
Self::KeyboardSoundEnabled => &mut config.keyboard_sound_enabled,
|
||||
Self::LeftHandedMouse => &mut config.left_handed_mouse,
|
||||
Self::NotificationsEnabled => &mut config.notifications_enabled,
|
||||
Self::NotificationsSoundEnabled => &mut config.notifications_sound_enabled,
|
||||
Self::OpaqueBackground => &mut config.opaque_background,
|
||||
Self::ScreenRenderDown => &mut config.screen_render_down,
|
||||
Self::SetsOnWatch => &mut config.sets_on_watch,
|
||||
Self::SpaceDragUnlocked => &mut config.space_drag_unlocked,
|
||||
Self::SpaceGravityEnabled => &mut config.space_gravity_enabled,
|
||||
Self::SpaceRotateUnlocked => &mut config.space_rotate_unlocked,
|
||||
Self::UprightScreenFix => &mut config.upright_screen_fix,
|
||||
Self::UsePassthrough => &mut config.use_passthrough,
|
||||
Self::UseSkybox => &mut config.use_skybox,
|
||||
Self::XwaylandByDefault => &mut config.xwayland_by_default,
|
||||
_ => panic!("Requested bool for non-bool SettingType"),
|
||||
}
|
||||
|
|
@ -332,18 +363,23 @@ impl SettingType {
|
|||
|
||||
pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 {
|
||||
match self {
|
||||
Self::GridOpacity => &mut config.grid_opacity,
|
||||
Self::LongPressDuration => &mut config.long_press_duration,
|
||||
Self::PointerLerpFactor => &mut config.pointer_lerp_factor,
|
||||
Self::ScrollSpeed => &mut config.scroll_speed,
|
||||
Self::SpaceDragMultiplier => &mut config.space_drag_multiplier,
|
||||
Self::SpaceGravityDamping => &mut config.space_gravity_damping,
|
||||
Self::SpaceGravityFlingStrength => &mut config.space_gravity_fling_strength,
|
||||
Self::SpaceGravityGravity => &mut config.space_gravity_gravity,
|
||||
Self::SpaceGravityGroundFriction => &mut config.space_gravity_ground_friction,
|
||||
Self::SpaceGravityFloorHeight => &mut config.space_gravity_floor_height,
|
||||
Self::UiAnimationSpeed => &mut config.ui_animation_speed,
|
||||
Self::UiGradientIntensity => &mut config.ui_gradient_intensity,
|
||||
Self::UiRoundMultiplier => &mut config.ui_round_multiplier,
|
||||
Self::ScrollSpeed => &mut config.scroll_speed,
|
||||
Self::LongPressDuration => &mut config.long_press_duration,
|
||||
Self::XrClickSensitivity => &mut config.xr_click_sensitivity,
|
||||
Self::XrClickSensitivityRelease => &mut config.xr_click_sensitivity_release,
|
||||
Self::SpaceDragMultiplier => &mut config.space_drag_multiplier,
|
||||
Self::PointerLerpFactor => &mut config.pointer_lerp_factor,
|
||||
Self::GridOpacity => &mut config.grid_opacity,
|
||||
Self::WatchViewAngleMax => &mut config.watch_view_angle_max,
|
||||
Self::WatchViewAngleMin => &mut config.watch_view_angle_min,
|
||||
Self::XrClickSensitivity => &mut config.xr_click_sensitivity,
|
||||
Self::XrClickSensitivityRelease => &mut config.xr_click_sensitivity_release,
|
||||
_ => panic!("Requested f32 for non-f32 SettingType"),
|
||||
}
|
||||
}
|
||||
|
|
@ -435,9 +471,16 @@ impl SettingType {
|
|||
Self::PointerLerpFactor => Ok("APP_SETTINGS.POINTER_LERP_FACTOR"),
|
||||
Self::ScreenRenderDown => Ok("APP_SETTINGS.SCREEN_RENDER_DOWN"),
|
||||
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
|
||||
Self::EnableWatch => Ok("APP_SETTINGS.ENABLE_WATCH"),
|
||||
Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"),
|
||||
Self::SpaceDragMultiplier => Ok("APP_SETTINGS.SPACE_DRAG_MULTIPLIER"),
|
||||
Self::SpaceDragUnlocked => Ok("APP_SETTINGS.SPACE_DRAG_UNLOCKED"),
|
||||
Self::SpaceGravityDamping => Ok("APP_SETTINGS.SPACE_GRAVITY_DAMPING"),
|
||||
Self::SpaceGravityEnabled => Ok("APP_SETTINGS.ENABLED"),
|
||||
Self::SpaceGravityFlingStrength => Ok("APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH"),
|
||||
Self::SpaceGravityGravity => Ok("APP_SETTINGS.SPACE_GRAVITY_GRAVITY"),
|
||||
Self::SpaceGravityGroundFriction => Ok("APP_SETTINGS.SPACE_GRAVITY_GROUND_FRICTION"),
|
||||
Self::SpaceGravityFloorHeight => Ok("APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT"),
|
||||
Self::SpaceRotateUnlocked => Ok("APP_SETTINGS.SPACE_ROTATE_UNLOCKED"),
|
||||
Self::UiAnimationSpeed => Ok("APP_SETTINGS.ANIMATION_SPEED"),
|
||||
Self::UiGradientIntensity => Ok("APP_SETTINGS.UI_GRADIENT_INTENSITY"),
|
||||
|
|
@ -466,13 +509,18 @@ impl SettingType {
|
|||
Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"),
|
||||
Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"),
|
||||
Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"),
|
||||
Self::SpaceGravityDamping => Some("APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP"),
|
||||
Self::SpaceGravityFlingStrength => Some("APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH_HELP"),
|
||||
Self::SpaceGravityFloorHeight => Some("APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT_HELP"),
|
||||
Self::SpaceGravityGravity => Some("APP_SETTINGS.SPACE_GRAVITY_GRAVITY_HELP"),
|
||||
Self::SpaceGravityGroundFriction => Some("APP_SETTINGS.SPACE_GRAVITY_GROUND_FRICTION_HELP"),
|
||||
Self::UprightScreenFix => Some("APP_SETTINGS.UPRIGHT_SCREEN_FIX_HELP"),
|
||||
Self::UsePassthrough => Some("APP_SETTINGS.USE_PASSTHROUGH_HELP"),
|
||||
Self::UseSkybox => Some("APP_SETTINGS.USE_SKYBOX_HELP"),
|
||||
Self::WatchViewAngleMax => Some("APP_SETTINGS.WATCH_VIEW_ANGLE_HELP"),
|
||||
Self::WatchViewAngleMin => Some("APP_SETTINGS.WATCH_VIEW_ANGLE_HELP"),
|
||||
Self::XrClickSensitivity => Some("APP_SETTINGS.XR_CLICK_SENSITIVITY_HELP"),
|
||||
Self::XrClickSensitivityRelease => Some("APP_SETTINGS.XR_CLICK_SENSITIVITY_HELP"),
|
||||
Self::WatchViewAngleMin => Some("APP_SETTINGS.WATCH_VIEW_ANGLE_HELP"),
|
||||
Self::WatchViewAngleMax => Some("APP_SETTINGS.WATCH_VIEW_ANGLE_HELP"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -575,6 +623,9 @@ impl<T> TabSettings<T> {
|
|||
TabNameEnum::Features => {
|
||||
self.current_tab = Some(Box::new(tab_features::State::mount(settings_mount_params)?));
|
||||
}
|
||||
TabNameEnum::SpaceDrag => {
|
||||
self.current_tab = Some(Box::new(tab_space_drag::State::mount(settings_mount_params)?));
|
||||
}
|
||||
TabNameEnum::Controls => {
|
||||
self.current_tab = Some(Box::new(tab_controls::State::mount(settings_mount_params)?));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,15 +13,6 @@ impl State {
|
|||
options_checkbox(par.mp, c, SettingType::NotificationsEnabled)?;
|
||||
options_checkbox(par.mp, c, SettingType::NotificationsSoundEnabled)?;
|
||||
options_checkbox(par.mp, c, SettingType::KeyboardSoundEnabled)?;
|
||||
if !par.feats.openxr || par.feats.monado {
|
||||
// monado or openvr
|
||||
options_checkbox(par.mp, c, SettingType::SpaceDragUnlocked)?;
|
||||
options_slider_f32(par.mp, c, SettingType::SpaceDragMultiplier, -10.0, 10.0, 0.5)?;
|
||||
}
|
||||
if par.feats.monado {
|
||||
// openvr can only ever rotate yaw
|
||||
options_checkbox(par.mp, c, SettingType::SpaceRotateUnlocked)?;
|
||||
}
|
||||
if !par.feats.openxr || par.feats.monado {
|
||||
// monado or openvr
|
||||
options_checkbox(par.mp, c, SettingType::BlockGameInput)?;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ impl State {
|
|||
options_slider_f32(par.mp, c, SettingType::UiAnimationSpeed, 0.5, 5.0, 0.1)?; // min, max, step
|
||||
options_slider_f32(par.mp, c, SettingType::UiGradientIntensity, 0.0, 1.0, 0.05)?; // min, max, step
|
||||
options_slider_f32(par.mp, c, SettingType::UiRoundMultiplier, 0.1, 5.0, 0.1)?;
|
||||
options_checkbox(par.mp, c, SettingType::EnableWatch)?;
|
||||
options_checkbox(par.mp, c, SettingType::SetsOnWatch)?;
|
||||
options_checkbox(par.mp, c, SettingType::Clock12h)?;
|
||||
Ok(State {})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
use wgui::{
|
||||
assets::AssetPath,
|
||||
i18n::Translation,
|
||||
layout::{Layout, LayoutTask, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
tab::settings::{
|
||||
SettingType, SettingsMountParams, SettingsTab,
|
||||
macros::{options_category, options_checkbox, options_slider_f32},
|
||||
},
|
||||
util::wgui_simple,
|
||||
};
|
||||
|
||||
pub struct State {
|
||||
id_space_gravity_parent: WidgetID,
|
||||
}
|
||||
|
||||
fn set_visible(parent: WidgetID, layout: &mut Layout, n: bool) {
|
||||
layout.tasks.push(LayoutTask::SetWidgetVisible(parent, n));
|
||||
}
|
||||
|
||||
impl SettingsTab for State {
|
||||
fn setting_updated(&mut self, sup: &mut super::SettingUpdatedParams) -> anyhow::Result<()> {
|
||||
if sup.setting_type == SettingType::SpaceGravityEnabled {
|
||||
set_visible(
|
||||
self.id_space_gravity_parent,
|
||||
sup.layout,
|
||||
sup.config.space_gravity_enabled,
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
|
||||
let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.SPACE_DRAG", "dashboard/drag.svg")?;
|
||||
|
||||
let globals = par.mp.layout.state.globals.clone();
|
||||
|
||||
let tab_state = wgui::parser::parse_from_assets(
|
||||
&ParseDocumentParams {
|
||||
globals,
|
||||
path: AssetPath::BuiltIn("gui/tab/settings_tab_space_drag.xml"),
|
||||
extra: Default::default(),
|
||||
},
|
||||
par.mp.layout,
|
||||
c,
|
||||
)?;
|
||||
|
||||
let id_common_options_parent = tab_state.get_widget_id("common_options_parent")?;
|
||||
let id_gravity_enabled_parent = tab_state.get_widget_id("gravity_enabled_parent")?;
|
||||
let id_space_gravity_parent = tab_state.get_widget_id("space_gravity_parent")?;
|
||||
|
||||
if !par.feats.openxr || par.feats.monado {
|
||||
// monado or openvr
|
||||
options_checkbox(par.mp, id_common_options_parent, SettingType::SpaceDragUnlocked)?;
|
||||
|
||||
options_slider_f32(
|
||||
par.mp,
|
||||
id_common_options_parent,
|
||||
SettingType::SpaceDragMultiplier,
|
||||
-10.0,
|
||||
10.0,
|
||||
0.5,
|
||||
)?;
|
||||
}
|
||||
|
||||
if par.feats.monado {
|
||||
// openvr can only ever rotate yaw
|
||||
options_checkbox(par.mp, id_common_options_parent, SettingType::SpaceRotateUnlocked)?;
|
||||
}
|
||||
|
||||
if par.feats.monado {
|
||||
/* space gravity section */
|
||||
options_checkbox(par.mp, id_gravity_enabled_parent, SettingType::SpaceGravityEnabled)?;
|
||||
|
||||
options_slider_f32(
|
||||
par.mp,
|
||||
id_space_gravity_parent,
|
||||
SettingType::SpaceGravityGravity,
|
||||
0.0,
|
||||
10.0,
|
||||
0.5,
|
||||
)?;
|
||||
options_slider_f32(
|
||||
par.mp,
|
||||
id_space_gravity_parent,
|
||||
SettingType::SpaceGravityDamping,
|
||||
0.1,
|
||||
1.0,
|
||||
0.01,
|
||||
)?;
|
||||
options_slider_f32(
|
||||
par.mp,
|
||||
id_space_gravity_parent,
|
||||
SettingType::SpaceGravityFlingStrength,
|
||||
0.0,
|
||||
3.0,
|
||||
0.1,
|
||||
)?;
|
||||
options_slider_f32(
|
||||
par.mp,
|
||||
id_space_gravity_parent,
|
||||
SettingType::SpaceGravityGroundFriction,
|
||||
0.0,
|
||||
1.0,
|
||||
0.01,
|
||||
)?;
|
||||
options_slider_f32(
|
||||
par.mp,
|
||||
id_space_gravity_parent,
|
||||
SettingType::SpaceGravityFloorHeight,
|
||||
-5.0,
|
||||
5.0,
|
||||
0.1,
|
||||
)?;
|
||||
} else {
|
||||
wgui_simple::create_label(
|
||||
par.mp.layout,
|
||||
id_gravity_enabled_parent,
|
||||
Translation::from_translation_key("APP_SETTINGS.NOT_SUPPORTED"),
|
||||
)?;
|
||||
}
|
||||
|
||||
set_visible(
|
||||
id_space_gravity_parent,
|
||||
par.mp.layout,
|
||||
par.mp.config.space_gravity_enabled,
|
||||
);
|
||||
|
||||
Ok(State {
|
||||
id_space_gravity_parent,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -6,12 +6,11 @@ use std::{
|
|||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::button::ComponentButton,
|
||||
event::{EventAlterables, StyleSetRequest},
|
||||
event::EventAlterables,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
taffy::Display,
|
||||
widget::label::WidgetLabel,
|
||||
};
|
||||
use wlx_common::config::GeneralConfig;
|
||||
|
|
@ -232,15 +231,7 @@ impl State {
|
|||
let popup = popup.upgrade().unwrap(); // safe
|
||||
let popup = popup.borrow_mut();
|
||||
let mounted_popup = popup.mounted_popup.as_ref().unwrap(); // safe;
|
||||
|
||||
alterables.set_style(
|
||||
mounted_popup.id_root,
|
||||
StyleSetRequest::Display(if idx == self.popup_stack.len() - 1 {
|
||||
Display::Flex
|
||||
} else {
|
||||
Display::None
|
||||
}),
|
||||
);
|
||||
alterables.set_widget_visible(mounted_popup.id_root, idx == self.popup_stack.len() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,10 +112,7 @@ impl View {
|
|||
fn fill_list(&mut self, layout: &mut Layout, games: Vec<steam_utils::RunningGame>) -> anyhow::Result<()> {
|
||||
if games.is_empty() {
|
||||
// hide self
|
||||
layout.tasks.push(LayoutTask::SetWidgetStyle(
|
||||
self.parent_id,
|
||||
StyleSetRequest::Display(Display::None),
|
||||
));
|
||||
layout.tasks.push(LayoutTask::SetWidgetVisible(self.parent_id, false));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use wgui::{
|
|||
checkbox::ComponentCheckbox,
|
||||
},
|
||||
drawing::Color,
|
||||
event::StyleSetRequest,
|
||||
font_config::WguiFontConfig,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
|
|
@ -134,14 +133,9 @@ impl TestbedGeneric {
|
|||
let div_visibility = parser_state.fetch_widget(&layout.state, "div_visibility")?;
|
||||
|
||||
cb_visible.on_toggle(Box::new(move |common, evt| {
|
||||
common.alterables.set_style(
|
||||
div_visibility.id,
|
||||
StyleSetRequest::Display(if evt.checked {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
}),
|
||||
);
|
||||
common
|
||||
.alterables
|
||||
.set_widget_visible(div_visibility.id, evt.checked);
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
pub mod input;
|
||||
pub mod playspace_common;
|
||||
|
||||
#[cfg(feature = "openvr")]
|
||||
pub mod openvr;
|
||||
|
|
|
|||
|
|
@ -146,8 +146,12 @@ pub fn openvr_run(
|
|||
let mut lines = LinePool::new(app.gfx.clone())?;
|
||||
let pointer_lines = [lines.allocate(), lines.allocate()];
|
||||
let mut current_lines = Vec::with_capacity(2);
|
||||
let mut last_frame_time = Instant::now();
|
||||
|
||||
'main_loop: loop {
|
||||
let now = Instant::now();
|
||||
app.delta_time = (now.duration_since(last_frame_time).as_secs_f32()).clamp(0.001, 0.2); // 5 - 1000 fps
|
||||
last_frame_time = now;
|
||||
let _ = overlay_mgr.wait_frame_sync(frame_timeout);
|
||||
|
||||
if !RUNNING.load(Ordering::Relaxed) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use ovr_overlay::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
backend::{input::InputState, task::PlayspaceTask},
|
||||
backend::{input::InputState, playspace_common, task::PlayspaceTask},
|
||||
state::AppState,
|
||||
windowing::manager::OverlayWindowManager,
|
||||
};
|
||||
|
|
@ -137,16 +137,7 @@ impl PlayspaceMover {
|
|||
}
|
||||
|
||||
let overlay_offset = data.pose.inverse().transform_vector3a(relative_pos) * -1.0;
|
||||
|
||||
overlays.values_mut().for_each(|overlay| {
|
||||
let Some(state) = overlay.config.active_state.as_mut() else {
|
||||
return;
|
||||
};
|
||||
if state.positioning.moves_with_space() {
|
||||
state.transform.translation += overlay_offset;
|
||||
overlay.config.dirty = true;
|
||||
}
|
||||
});
|
||||
playspace_common::shift_overlays(overlays, overlay_offset);
|
||||
|
||||
data.pose.translation += relative_pos;
|
||||
data.hand_pose = new_hand;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ pub fn openxr_run(
|
|||
|
||||
app.monado_state_init();
|
||||
|
||||
let mut playspace = app.monado_state.as_mut().and_then(|m| {
|
||||
let mut playspace_mover = app.monado_state.as_mut().and_then(|m| {
|
||||
playspace::PlayspaceMover::new(&mut m.ipc)
|
||||
.map_err(|e| log::warn!("Will not use Monado playspace mover: {e}"))
|
||||
.ok()
|
||||
|
|
@ -155,8 +155,12 @@ pub fn openxr_run(
|
|||
|
||||
let mut main_session_visible = false;
|
||||
let mut environment_blend_mode = modes[0];
|
||||
let mut last_frame_time = Instant::now();
|
||||
|
||||
'main_loop: loop {
|
||||
let now = Instant::now();
|
||||
app.delta_time = (now.duration_since(last_frame_time).as_secs_f32()).clamp(0.001, 0.2); // 5 - 1000 fps
|
||||
last_frame_time = now;
|
||||
let cur_frame = FRAME_COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
if !RUNNING.load(Ordering::Relaxed) {
|
||||
|
|
@ -296,8 +300,8 @@ pub fn openxr_run(
|
|||
.enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard));
|
||||
}
|
||||
|
||||
if let Some(ref mut space_mover) = playspace {
|
||||
space_mover.update(&mut overlays, &mut app);
|
||||
if let Some(ref mut playspace_mover) = playspace_mover {
|
||||
playspace_mover.update(&mut overlays, &mut app);
|
||||
}
|
||||
|
||||
for o in overlays.values_mut() {
|
||||
|
|
@ -346,9 +350,12 @@ pub fn openxr_run(
|
|||
app.hid_provider.inner.commit();
|
||||
|
||||
let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic
|
||||
if watch.config.active_state.is_none() {
|
||||
watch.config.activate(&mut app);
|
||||
}
|
||||
let watch_state = watch.config.active_state.as_mut().unwrap();
|
||||
let watch_transform = watch_state.transform;
|
||||
if watch_state.alpha < 0.05 {
|
||||
if watch_state.alpha < 0.05 || !app.session.config.enable_watch {
|
||||
//FIXME: Temporary workaround for Monado bug
|
||||
watch_state.transform = Affine3A::from_scale(Vec3 {
|
||||
x: 0.001,
|
||||
|
|
@ -481,8 +488,8 @@ pub fn openxr_run(
|
|||
overlays.handle_task(&mut app, task)?;
|
||||
}
|
||||
TaskType::Playspace(task) => {
|
||||
if let Some(playspace) = playspace.as_mut() {
|
||||
playspace.handle_task(&mut app, task);
|
||||
if let Some(playspace_mover) = playspace_mover.as_mut() {
|
||||
playspace_mover.handle_task(&mut app, task);
|
||||
}
|
||||
}
|
||||
TaskType::OpenXR(task) => {
|
||||
|
|
@ -510,7 +517,13 @@ pub fn openxr_run(
|
|||
|
||||
//FIXME: Temporary workaround for Monado bug
|
||||
let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic
|
||||
watch.config.active_state.as_mut().unwrap().transform = watch_transform;
|
||||
|
||||
if let Some(state) = watch.config.active_state.as_mut() {
|
||||
state.transform = watch_transform
|
||||
}
|
||||
if !app.session.config.enable_watch {
|
||||
watch.config.deactivate();
|
||||
}
|
||||
} // main_loop
|
||||
|
||||
if let (Some(blocker), Some(monado)) = (blocker, app.monado_state.as_mut()) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ use libmonado::{MndResult, Monado, Pose, ReferenceSpaceType};
|
|||
use wgui::log::LogErr;
|
||||
|
||||
use crate::{
|
||||
backend::{input::InputState, task::PlayspaceTask},
|
||||
backend::{
|
||||
input::InputState,
|
||||
playspace_common::{self, SpaceGravity, SpaceGravityUpdateParams},
|
||||
task::PlayspaceTask,
|
||||
},
|
||||
state::AppState,
|
||||
windowing::manager::OverlayWindowManager,
|
||||
};
|
||||
|
|
@ -19,6 +23,7 @@ struct MoverData<T> {
|
|||
pub(super) struct PlayspaceMover {
|
||||
drag: Option<MoverData<Vec3A>>,
|
||||
rotate: Option<MoverData<Quat>>,
|
||||
gravity: SpaceGravity,
|
||||
}
|
||||
|
||||
impl PlayspaceMover {
|
||||
|
|
@ -35,6 +40,7 @@ impl PlayspaceMover {
|
|||
Ok(Self {
|
||||
drag: None,
|
||||
rotate: None,
|
||||
gravity: SpaceGravity::new(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -140,21 +146,27 @@ impl PlayspaceMover {
|
|||
}
|
||||
|
||||
if let Some(mut data) = self.drag.take() {
|
||||
let pointer = &app.input_state.pointers[data.hand];
|
||||
if !pointer.now.space_drag {
|
||||
log::info!("End space drag");
|
||||
return;
|
||||
}
|
||||
|
||||
let new_hand = data
|
||||
.pose
|
||||
.transform_point3a(app.input_state.pointers[data.hand].raw_pose.translation);
|
||||
|
||||
let relative_pos = if app.session.config.space_drag_unlocked {
|
||||
new_hand - data.hand_pose
|
||||
} else {
|
||||
vec3a(0., new_hand.y - data.hand_pose.y, 0.)
|
||||
} * app.session.config.space_drag_multiplier;
|
||||
let pointer = &app.input_state.pointers[data.hand];
|
||||
|
||||
if !pointer.now.space_drag {
|
||||
self.gravity.mark_end_drag(
|
||||
&app.session.config,
|
||||
relative_pos,
|
||||
data.pose.translation,
|
||||
app.delta_time,
|
||||
);
|
||||
|
||||
log::info!("End space drag");
|
||||
return;
|
||||
}
|
||||
|
||||
if relative_pos.length_squared() > 1000.0 {
|
||||
log::warn!("Space drag too fast, ignoring");
|
||||
|
|
@ -162,16 +174,7 @@ impl PlayspaceMover {
|
|||
}
|
||||
|
||||
let overlay_offset = data.pose.inverse().transform_vector3a(relative_pos) * -1.0;
|
||||
|
||||
overlays.values_mut().for_each(|overlay| {
|
||||
let Some(state) = overlay.config.active_state.as_mut() else {
|
||||
return;
|
||||
};
|
||||
if state.positioning.moves_with_space() {
|
||||
state.transform.translation += overlay_offset;
|
||||
}
|
||||
overlay.config.dirty = true;
|
||||
});
|
||||
playspace_common::shift_overlays(overlays, overlay_offset);
|
||||
|
||||
data.pose.translation += relative_pos;
|
||||
data.hand_pose = new_hand;
|
||||
|
|
@ -207,6 +210,20 @@ impl PlayspaceMover {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(res) = self.gravity.update(SpaceGravityUpdateParams {
|
||||
dt: app.delta_time,
|
||||
dragging: self.drag.is_some(),
|
||||
config: &app.session.config,
|
||||
floor_height: app.session.config.space_gravity_floor_height,
|
||||
}) {
|
||||
apply_offset(
|
||||
Affine3A::from_translation(res.playspace_pos.into()),
|
||||
&mut monado.ipc,
|
||||
);
|
||||
|
||||
playspace_common::shift_overlays(overlays, -res.playspace_pos_offset);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recenter(&mut self, input: &InputState, monado: &mut Monado) {
|
||||
|
|
@ -232,6 +249,8 @@ impl PlayspaceMover {
|
|||
let _ = monado
|
||||
.set_reference_space_offset(ReferenceSpaceType::Stage, pose)
|
||||
.inspect_err(|e| log::warn!("Could not recenter due to libmonado error: {e:?}"));
|
||||
|
||||
self.gravity.reset();
|
||||
}
|
||||
|
||||
pub fn reset_offset(&mut self, monado: &mut Monado) {
|
||||
|
|
@ -244,6 +263,7 @@ impl PlayspaceMover {
|
|||
self.rotate = None;
|
||||
}
|
||||
|
||||
self.gravity.reset();
|
||||
apply_offset(Affine3A::IDENTITY, monado);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
use glam::Vec3A;
|
||||
use wlx_common::config::GeneralConfig;
|
||||
|
||||
use crate::windowing::manager::OverlayWindowManager;
|
||||
|
||||
pub struct SpaceGravityUpdateParams<'a> {
|
||||
pub dt: f32,
|
||||
pub dragging: bool,
|
||||
pub config: &'a GeneralConfig,
|
||||
pub floor_height: f32,
|
||||
}
|
||||
|
||||
pub struct SpaceGravity {
|
||||
velocity: Vec3A,
|
||||
space_pos: Vec3A,
|
||||
}
|
||||
|
||||
pub fn shift_overlays<OverlayData>(
|
||||
overlays: &mut OverlayWindowManager<OverlayData>,
|
||||
overlay_offset: Vec3A,
|
||||
) {
|
||||
overlays.values_mut().for_each(|overlay| {
|
||||
let Some(state) = overlay.config.active_state.as_mut() else {
|
||||
return;
|
||||
};
|
||||
if state.positioning.moves_with_space() {
|
||||
state.transform.translation += overlay_offset;
|
||||
}
|
||||
overlay.config.dirty = true;
|
||||
});
|
||||
}
|
||||
|
||||
pub struct SpaceGravityUpdateResult {
|
||||
pub playspace_pos: Vec3A,
|
||||
pub playspace_pos_offset: Vec3A, // position difference compared to previous update() call
|
||||
}
|
||||
|
||||
impl SpaceGravity {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
velocity: Vec3A::default(),
|
||||
space_pos: Vec3A::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mark_end_drag(
|
||||
&mut self,
|
||||
config: &GeneralConfig,
|
||||
hand_pos_diff: Vec3A,
|
||||
space_pos: Vec3A,
|
||||
dt: f32,
|
||||
) {
|
||||
if config.space_gravity_enabled {
|
||||
self.velocity = hand_pos_diff * config.space_gravity_fling_strength / dt;
|
||||
self.space_pos = space_pos;
|
||||
} else {
|
||||
self.reset();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.velocity = Vec3A::default();
|
||||
self.space_pos = Vec3A::default();
|
||||
}
|
||||
|
||||
pub fn update(&mut self, par: SpaceGravityUpdateParams) -> Option<SpaceGravityUpdateResult> {
|
||||
if par.dragging || !par.config.space_gravity_enabled {
|
||||
return None;
|
||||
}
|
||||
|
||||
let prev_pos = self.space_pos;
|
||||
|
||||
self.velocity.y += par.config.space_gravity_gravity * par.dt;
|
||||
|
||||
// terminal velocity
|
||||
self.velocity.y = self.velocity.y.min(200.0);
|
||||
|
||||
self.velocity *= (par.config.space_gravity_damping).powf(par.dt * 10.0);
|
||||
|
||||
self.space_pos += self.velocity * par.dt;
|
||||
|
||||
self.space_pos.y = self.space_pos.y.min(par.floor_height);
|
||||
|
||||
if self.space_pos.y >= par.floor_height
|
||||
/* at floor height or below */
|
||||
{
|
||||
// apply ground friction
|
||||
self.velocity *= 1.0 - par.config.space_gravity_ground_friction * par.dt * 10.0;
|
||||
}
|
||||
|
||||
if self.velocity.length_squared() > 0.00003 {
|
||||
// Space position changed
|
||||
return Some(SpaceGravityUpdateResult {
|
||||
playspace_pos: self.space_pos,
|
||||
playspace_pos_offset: self.space_pos - prev_pos,
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -145,6 +145,7 @@ pub struct AutoSettings {
|
|||
pub keyboard_sound_enabled: bool,
|
||||
pub upright_screen_fix: bool,
|
||||
pub double_cursor_fix: bool,
|
||||
pub enable_watch: bool,
|
||||
pub sets_on_watch: bool,
|
||||
pub hide_grab_help: bool,
|
||||
pub xr_click_sensitivity: f32,
|
||||
|
|
@ -165,6 +166,12 @@ pub struct AutoSettings {
|
|||
pub screen_render_down: bool,
|
||||
pub pointer_lerp_factor: f32,
|
||||
pub space_drag_unlocked: bool,
|
||||
pub space_gravity_damping: f32,
|
||||
pub space_gravity_enabled: bool,
|
||||
pub space_gravity_fling_strength: f32,
|
||||
pub space_gravity_gravity: f32,
|
||||
pub space_gravity_ground_friction: f32,
|
||||
pub space_gravity_floor_height: f32,
|
||||
pub space_rotate_unlocked: bool,
|
||||
pub clock_12h: bool,
|
||||
pub hide_username: bool,
|
||||
|
|
@ -200,6 +207,7 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
|||
keyboard_sound_enabled: config.keyboard_sound_enabled,
|
||||
upright_screen_fix: config.upright_screen_fix,
|
||||
double_cursor_fix: config.double_cursor_fix,
|
||||
enable_watch: config.enable_watch,
|
||||
sets_on_watch: config.sets_on_watch,
|
||||
hide_grab_help: config.hide_grab_help,
|
||||
xr_click_sensitivity: config.xr_click_sensitivity,
|
||||
|
|
@ -220,6 +228,12 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
|||
screen_render_down: config.screen_render_down,
|
||||
pointer_lerp_factor: config.pointer_lerp_factor,
|
||||
space_drag_unlocked: config.space_drag_unlocked,
|
||||
space_gravity_damping: config.space_gravity_damping,
|
||||
space_gravity_enabled: config.space_gravity_enabled,
|
||||
space_gravity_fling_strength: config.space_gravity_fling_strength,
|
||||
space_gravity_gravity: config.space_gravity_gravity,
|
||||
space_gravity_ground_friction: config.space_gravity_ground_friction,
|
||||
space_gravity_floor_height: config.space_gravity_floor_height,
|
||||
space_rotate_unlocked: config.space_rotate_unlocked,
|
||||
clock_12h: config.clock_12h,
|
||||
hide_username: config.hide_username,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ use wgui::{
|
|||
self, CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState, parse_color_hex,
|
||||
},
|
||||
renderer_vk::{context::Context as WguiContext, text::custom_glyph::CustomGlyphData},
|
||||
taffy,
|
||||
widget::{
|
||||
EventResult, image::WidgetImage, label::WidgetLabel, rectangle::WidgetRectangle,
|
||||
sprite::WidgetSprite,
|
||||
|
|
@ -552,15 +551,7 @@ pub fn apply_custom_command<T>(
|
|||
.parser_state
|
||||
.get_widget_id(element)
|
||||
.context("No widget with such id.")?;
|
||||
|
||||
let display = if *visible {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
|
||||
com.alterables
|
||||
.set_style(wid, wgui::event::StyleSetRequest::Display(display));
|
||||
com.alterables.set_widget_visible(wid, *visible);
|
||||
com.alterables.mark_redraw();
|
||||
}
|
||||
ModifyPanelCommand::SetValue(value_str) => {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use glam::{Affine3A, Quat, Vec3};
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use wgui::event::{EventAlterables, StyleSetRequest};
|
||||
use wgui::event::EventAlterables;
|
||||
use wgui::parser::Fetchable;
|
||||
use wgui::taffy;
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
use crate::gui::panel::GuiPanel;
|
||||
|
|
@ -84,13 +83,7 @@ pub fn create_grab_help(app: &mut AppState) -> anyhow::Result<OverlayWindowConfi
|
|||
};
|
||||
|
||||
for id in &all {
|
||||
let display = if *id == show_id {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
|
||||
alterables.set_style(*id, StyleSetRequest::Display(display));
|
||||
alterables.set_widget_visible(*id, *id == show_id);
|
||||
}
|
||||
|
||||
panel.layout.process_alterables(alterables)?;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use wgui::{event::StyleSetRequest, parser::Fetchable, taffy};
|
||||
use wgui::parser::Fetchable;
|
||||
use wlx_common::{common::LeftRight, windowing::Positioning};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -47,26 +47,12 @@ pub fn new_pos_tab_handler(
|
|||
})
|
||||
}),
|
||||
Some(Box::new(move |common, state| {
|
||||
let interpolation_disp = if state.has_lerp {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
|
||||
common.alterables.set_style(
|
||||
interpolation_id,
|
||||
StyleSetRequest::Display(interpolation_disp),
|
||||
);
|
||||
|
||||
let align_to_hmd_disp = if state.has_align {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
|
||||
common
|
||||
.alterables
|
||||
.set_style(align_to_hmd_id, StyleSetRequest::Display(align_to_hmd_disp));
|
||||
.set_widget_visible(interpolation_id, state.has_lerp);
|
||||
common
|
||||
.alterables
|
||||
.set_widget_visible(align_to_hmd_id, state.has_align);
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,15 +72,9 @@ impl ButtonPaneTabSwitcher {
|
|||
return;
|
||||
};
|
||||
|
||||
let display = if visible {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
|
||||
common
|
||||
.alterables
|
||||
.set_style(data.get_rect(), StyleSetRequest::Display(display));
|
||||
.set_widget_visible(data.get_rect(), visible);
|
||||
}
|
||||
|
||||
pub fn reset(&mut self, common: &mut CallbackDataCommon) {
|
||||
|
|
|
|||
|
|
@ -238,16 +238,20 @@ impl OverlayBackend for ScreenBackend {
|
|||
}
|
||||
|
||||
if let Some(pipeline) = self.pipeline.as_mut() {
|
||||
if self.meta.is_some_and(|old| old.extent != meta.extent) {
|
||||
pipeline.set_extent(
|
||||
if self.meta.is_some_and(|old| old.extent != meta.extent)
|
||||
|| frame.format.transform != pipeline.transform()
|
||||
{
|
||||
pipeline.set_layout(
|
||||
app,
|
||||
[meta.extent[0] as _, meta.extent[1] as _],
|
||||
[0., 0.],
|
||||
frame.format.transform,
|
||||
)?;
|
||||
self.interaction_transform = Some(ui_transform(meta.extent));
|
||||
}
|
||||
} else {
|
||||
let pipeline = ScreenPipeline::new(&meta, app, stereo, [0., 0.])?;
|
||||
let pipeline =
|
||||
ScreenPipeline::new(&meta, app, stereo, [0., 0.], frame.format.transform)?;
|
||||
self.pipeline = Some(pipeline);
|
||||
self.interaction_transform = Some(ui_transform(meta.extent));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use std::{
|
||||
f32::consts::PI,
|
||||
os::fd::AsRawFd,
|
||||
sync::{Arc, OnceLock},
|
||||
};
|
||||
|
||||
use glam::{Affine3A, Vec3};
|
||||
use glam::Affine3A;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, Subbuffer},
|
||||
|
|
@ -55,6 +54,7 @@ pub struct ScreenPipeline {
|
|||
pipeline: Arc<WGfxPipeline<Vert2Uv>>,
|
||||
extentf: [f32; 2],
|
||||
offsetf: [f32; 2],
|
||||
transform: wlx_frame::Transform,
|
||||
stereo: StereoMode,
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +64,7 @@ impl ScreenPipeline {
|
|||
app: &mut AppState,
|
||||
stereo: StereoMode,
|
||||
offsetf: [f32; 2],
|
||||
transform: wlx_frame::Transform,
|
||||
) -> anyhow::Result<Self> {
|
||||
let extentf = [meta.extent[0] as f32, meta.extent[1] as f32];
|
||||
|
||||
|
|
@ -81,6 +82,7 @@ impl ScreenPipeline {
|
|||
pipeline,
|
||||
extentf,
|
||||
offsetf,
|
||||
transform,
|
||||
stereo,
|
||||
};
|
||||
me.ensure_stereo(stereo);
|
||||
|
|
@ -96,6 +98,10 @@ impl ScreenPipeline {
|
|||
self.pass.clear(); // ensure_depth will repopulate
|
||||
}
|
||||
|
||||
pub const fn transform(&self) -> wlx_frame::Transform {
|
||||
self.transform
|
||||
}
|
||||
|
||||
fn ensure_depth(&mut self, app: &mut AppState, depth: usize) -> anyhow::Result<()> {
|
||||
while self.pass.len() < depth {
|
||||
self.pass.push(Self::create_pass(
|
||||
|
|
@ -111,20 +117,22 @@ impl ScreenPipeline {
|
|||
}
|
||||
|
||||
for (eye, current) in self.pass.iter_mut().enumerate() {
|
||||
let verts = stereo_mode_to_verts(self.stereo, eye);
|
||||
let verts = stereo_mode_to_verts(self.stereo, eye, self.transform);
|
||||
current.buf_vert.write()?.copy_from_slice(&verts);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_extent(
|
||||
pub fn set_layout(
|
||||
&mut self,
|
||||
app: &mut AppState,
|
||||
extentf: [f32; 2],
|
||||
offsetf: [f32; 2],
|
||||
transform: wlx_frame::Transform,
|
||||
) -> anyhow::Result<()> {
|
||||
self.extentf = extentf;
|
||||
self.offsetf = offsetf;
|
||||
self.transform = transform;
|
||||
self.pass.clear();
|
||||
|
||||
self.mouse = Self::create_mouse_pass(app, self.pipeline.clone(), extentf, offsetf)?;
|
||||
|
|
@ -241,13 +249,31 @@ impl ScreenPipeline {
|
|||
}
|
||||
}
|
||||
|
||||
fn stereo_mode_to_verts(stereo: StereoMode, array_index: usize) -> [Vert2Uv; 4] {
|
||||
fn transform_uv(uv: [f32; 2], transform: wlx_frame::Transform) -> [f32; 2] {
|
||||
let [u, v] = uv;
|
||||
match transform {
|
||||
wlx_frame::Transform::Normal | wlx_frame::Transform::Undefined => [u, v],
|
||||
wlx_frame::Transform::Rotated90 => [v, 1.0 - u],
|
||||
wlx_frame::Transform::Rotated180 => [1.0 - u, 1.0 - v],
|
||||
wlx_frame::Transform::Rotated270 => [1.0 - v, u],
|
||||
wlx_frame::Transform::Flipped => [1.0 - u, v],
|
||||
wlx_frame::Transform::Flipped90 => [v, u],
|
||||
wlx_frame::Transform::Flipped180 => [u, 1.0 - v],
|
||||
wlx_frame::Transform::Flipped270 => [1.0 - v, 1.0 - u],
|
||||
}
|
||||
}
|
||||
|
||||
fn stereo_mode_to_verts(
|
||||
stereo: StereoMode,
|
||||
array_index: usize,
|
||||
transform: wlx_frame::Transform,
|
||||
) -> [Vert2Uv; 4] {
|
||||
let eye = match stereo {
|
||||
StereoMode::RightLeft | StereoMode::BottomTop => (1 - array_index) as f32,
|
||||
_ => array_index as f32,
|
||||
};
|
||||
|
||||
match stereo {
|
||||
let mut verts = match stereo {
|
||||
StereoMode::None => [
|
||||
Vert2Uv {
|
||||
in_pos: [0., 0.],
|
||||
|
|
@ -302,7 +328,13 @@ fn stereo_mode_to_verts(stereo: StereoMode, array_index: usize) -> [Vert2Uv; 4]
|
|||
in_uv: [1., 0.5 + eye * 0.5],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
for vert in &mut verts {
|
||||
vert.in_uv = transform_uv(vert.in_uv, transform);
|
||||
}
|
||||
|
||||
verts
|
||||
}
|
||||
|
||||
static DMA_ALLOCATOR: OnceLock<Arc<dyn MemoryAllocator>> = OnceLock::new();
|
||||
|
|
@ -460,7 +492,7 @@ impl WlxCaptureOut {
|
|||
FrameMeta {
|
||||
clear: WGfxClearMode::DontCare,
|
||||
extent: extent_from_format(self.format, config),
|
||||
transform: affine_from_format(&self.format),
|
||||
transform: Affine3A::IDENTITY,
|
||||
format: self.image.format(),
|
||||
stereo,
|
||||
}
|
||||
|
|
@ -585,13 +617,14 @@ pub(super) fn receive_callback(me: &WlxCaptureIn, frame: WlxFrame) -> Option<Wlx
|
|||
mouse: frame.mouse,
|
||||
})
|
||||
}
|
||||
WlxFrame::Implicit => {
|
||||
WlxFrame::Implicit(transform) => {
|
||||
log::trace!("{}: New Implicit frame", me.name);
|
||||
|
||||
let Some((image, format)) = me.dma_exporter.as_ref().unwrap().get_current() else {
|
||||
let Some((image, mut format)) = me.dma_exporter.as_ref().unwrap().get_current() else {
|
||||
log::error!("{}: Implicit frame is missing!", me.name);
|
||||
return None;
|
||||
};
|
||||
format.transform = transform;
|
||||
|
||||
Some(WlxCaptureOut {
|
||||
image,
|
||||
|
|
@ -676,6 +709,14 @@ const fn receive_callback_dummy(_: &DummyDrmExporter, frame: WlxFrame) -> Option
|
|||
}
|
||||
|
||||
fn extent_from_format(fmt: FrameFormat, config: &GeneralConfig) -> [u32; 2] {
|
||||
let (width, height) = match fmt.transform {
|
||||
wlx_frame::Transform::Rotated90
|
||||
| wlx_frame::Transform::Rotated270
|
||||
| wlx_frame::Transform::Flipped90
|
||||
| wlx_frame::Transform::Flipped270 => (fmt.height, fmt.width),
|
||||
_ => (fmt.width, fmt.height),
|
||||
};
|
||||
|
||||
// screens above a certain resolution will have severe aliasing
|
||||
let height_limit = if config.screen_render_down {
|
||||
u32::from(config.screen_max_height.min(2560))
|
||||
|
|
@ -683,36 +724,11 @@ fn extent_from_format(fmt: FrameFormat, config: &GeneralConfig) -> [u32; 2] {
|
|||
2560
|
||||
};
|
||||
|
||||
let h = fmt.height.min(height_limit);
|
||||
let w = (fmt.width as f32 / fmt.height as f32 * h as f32) as u32;
|
||||
let h = height.min(height_limit);
|
||||
let w = (width as f32 / height as f32 * h as f32) as u32;
|
||||
[w, h]
|
||||
}
|
||||
|
||||
fn affine_from_format(format: &FrameFormat) -> Affine3A {
|
||||
const FLIP_X: Vec3 = Vec3 {
|
||||
x: -1.0,
|
||||
y: 1.0,
|
||||
z: 1.0,
|
||||
};
|
||||
|
||||
match format.transform {
|
||||
wlx_frame::Transform::Rotated90 => Affine3A::from_rotation_z(-PI / 2.0),
|
||||
wlx_frame::Transform::Rotated180 => Affine3A::from_rotation_z(PI),
|
||||
wlx_frame::Transform::Rotated270 => Affine3A::from_rotation_z(PI / 2.0),
|
||||
wlx_frame::Transform::Flipped => Affine3A::from_scale(FLIP_X),
|
||||
wlx_frame::Transform::Flipped90 => {
|
||||
Affine3A::from_scale(FLIP_X) * Affine3A::from_rotation_z(-PI / 2.0)
|
||||
}
|
||||
wlx_frame::Transform::Flipped180 => {
|
||||
Affine3A::from_scale(FLIP_X) * Affine3A::from_rotation_z(PI)
|
||||
}
|
||||
wlx_frame::Transform::Flipped270 => {
|
||||
Affine3A::from_scale(FLIP_X) * Affine3A::from_rotation_z(PI / 2.0)
|
||||
}
|
||||
_ => Affine3A::IDENTITY,
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! new_wlx_capture {
|
||||
($capture_queue:expr, $capture:expr) => {
|
||||
if $capture_queue.is_none() {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ use glam::{Affine3A, Quat, Vec3, vec3};
|
|||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::button::ComponentButton,
|
||||
event::StyleSetRequest,
|
||||
parser::{Fetchable, ParseDocumentParams},
|
||||
taffy,
|
||||
};
|
||||
use wlx_common::{
|
||||
common::LeftRight,
|
||||
|
|
@ -156,17 +154,17 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
|||
angle_fade: true,
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
show_on_spawn: true,
|
||||
show_on_spawn: app.session.config.enable_watch,
|
||||
global: true,
|
||||
..OverlayWindowConfig::from_backend(Box::new(panel))
|
||||
})
|
||||
}
|
||||
|
||||
fn sets_or_overlays(panel: &mut GuiPanel<WatchState>, app: &mut AppState) {
|
||||
let display = if app.session.config.sets_on_watch {
|
||||
[taffy::Display::None, taffy::Display::Flex]
|
||||
let visible = if app.session.config.sets_on_watch {
|
||||
[false, true]
|
||||
} else {
|
||||
[taffy::Display::Flex, taffy::Display::None]
|
||||
[true, false]
|
||||
};
|
||||
|
||||
let widget = [
|
||||
|
|
@ -184,6 +182,6 @@ fn sets_or_overlays(panel: &mut GuiPanel<WatchState>, app: &mut AppState) {
|
|||
panel
|
||||
.layout
|
||||
.alterables
|
||||
.set_style(widget[i], StyleSetRequest::Display(display[i]));
|
||||
.set_widget_visible(widget[i], visible[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use wgui::{
|
|||
parser::Fetchable,
|
||||
widget::{EventResult, label::WidgetLabel},
|
||||
};
|
||||
use wlx_capture::frame::MouseMeta;
|
||||
use wlx_capture::frame::{MouseMeta, Transform};
|
||||
use wlx_common::{
|
||||
overlays::{BackendAttrib, BackendAttribValue, StereoMode},
|
||||
windowing::{OverlayWindowState, Positioning},
|
||||
|
|
@ -348,10 +348,11 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
|
||||
if let Some(pipeline) = self.pipeline.as_mut() {
|
||||
if self.inner_extent != inner_extent {
|
||||
pipeline.set_extent(
|
||||
pipeline.set_layout(
|
||||
app,
|
||||
[inner_extent[0] as _, inner_extent[1] as _],
|
||||
[BORDER_SIZE as _, (BAR_SIZE + BORDER_SIZE) as _],
|
||||
Transform::Normal,
|
||||
)?;
|
||||
self.apply_extent(app, &meta)?;
|
||||
self.inner_extent = inner_extent;
|
||||
|
|
@ -362,6 +363,7 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
app,
|
||||
self.stereo.unwrap_or(StereoMode::None),
|
||||
[BORDER_SIZE as _, (BAR_SIZE + BORDER_SIZE) as _],
|
||||
Transform::Normal,
|
||||
)?;
|
||||
self.apply_extent(app, &meta)?;
|
||||
self.pipeline = Some(pipeline);
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@
|
|||
# The settings are here for reference only.
|
||||
# Probably don't include them in your config file.
|
||||
|
||||
## The watch will be enabled
|
||||
#enable_watch: true
|
||||
|
||||
## The bottom of the watch will list sets instead of overlays.
|
||||
#sets_on_watch: false
|
||||
|
||||
|
|
@ -117,6 +120,21 @@
|
|||
## can rotate in any axis. Imagine horizon mode².
|
||||
#space_rotate_unlocked: false
|
||||
|
||||
## Space gravity: downward acceleration speed
|
||||
#space_gravity_gravity: 2.0
|
||||
|
||||
## Space gravity: velocity damping (0.98 = gentle slowdown, 0.5 = heavy drag)
|
||||
#space_gravity_damping: 0.98
|
||||
|
||||
## Space gravity: multiplier for "throwing" yourself via space drag momentum
|
||||
#space_gravity_fling_strength: 1.0
|
||||
|
||||
## Space gravity: floor height (Y position where gravity stops)
|
||||
#space_gravity_floor_height: 0.0
|
||||
|
||||
## Space gravity: ground friction when touching the floor
|
||||
#space_gravity_ground_friction: 1.0
|
||||
|
||||
## Monado/WiVRn only. Use passthrough camera if the headset supports it.
|
||||
## If disabled, the skybox will be shown.
|
||||
#use_passthrough: true
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ pub struct AppState {
|
|||
|
||||
#[cfg(feature = "openxr")]
|
||||
pub monado_state: Option<backend::openxr::monado_state::MonadoState>,
|
||||
|
||||
pub delta_time: f32,
|
||||
}
|
||||
|
||||
#[allow(unused_mut)]
|
||||
|
|
@ -188,6 +190,8 @@ impl AppState {
|
|||
|
||||
#[cfg(feature = "openxr")]
|
||||
monado_state: None,
|
||||
|
||||
delta_time: 1.0 / 120.0,
|
||||
};
|
||||
|
||||
if let Some(error_toast) = hid_error {
|
||||
|
|
|
|||
|
|
@ -288,6 +288,16 @@ where
|
|||
self.sets_changed(app);
|
||||
}
|
||||
OverlayTask::SettingsChanged => {
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
if app.session.config.enable_watch != watch.config.active_state.is_some() {
|
||||
if watch.config.active_state.is_some() {
|
||||
watch.config.deactivate();
|
||||
} else {
|
||||
watch.config.activate(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for o in self.overlays.values_mut() {
|
||||
let _ = o
|
||||
.config
|
||||
|
|
|
|||
|
|
@ -123,14 +123,7 @@ fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State)
|
|||
}
|
||||
|
||||
// Cursor
|
||||
common.alterables.set_style(
|
||||
data.id_rect_cursor,
|
||||
StyleSetRequest::Display(if state.focused {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
}),
|
||||
);
|
||||
common.alterables.set_widget_visible(data.id_rect_cursor, state.focused);
|
||||
|
||||
state.first_refresh = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -346,8 +346,8 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
const BODY_COLOR: drawing::Color = drawing::Color::new(0.6, 0.65, 0.7, 0.2);
|
||||
const BODY_BORDER_COLOR: drawing::Color = drawing::Color::new(0.4, 0.45, 0.5, 1.0);
|
||||
const BODY_COLOR: drawing::Color = drawing::Color::new(0.6, 0.65, 0.7, 0.1);
|
||||
const BODY_BORDER_COLOR: drawing::Color = drawing::Color::new(0.4, 0.45, 0.5, 0.6);
|
||||
const HANDLE_BORDER_COLOR: drawing::Color = drawing::Color::new(0.85, 0.85, 0.85, 1.0);
|
||||
const HANDLE_BORDER_COLOR_HOVERED: drawing::Color = drawing::Color::new(0.0, 0.0, 0.0, 1.0);
|
||||
const HANDLE_COLOR: drawing::Color = drawing::Color::new(1.0, 1.0, 1.0, 1.0);
|
||||
|
|
|
|||
|
|
@ -138,6 +138,17 @@ impl EventAlterables {
|
|||
self.style_set_requests.push((widget_id, request));
|
||||
}
|
||||
|
||||
pub fn set_widget_visible(&mut self, widget_id: WidgetID, visible: bool) {
|
||||
self.style_set_requests.push((
|
||||
widget_id,
|
||||
StyleSetRequest::Display(if visible {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn mark_dirty(&mut self, widget_id: WidgetID) {
|
||||
self.dirty_widgets.push(widget_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
drawing::{
|
||||
self, ANSI_BOLD_CODE, ANSI_RESET_CODE, Boundary, PushScissorStackResult, push_scissor_stack, push_transform_stack,
|
||||
},
|
||||
event::{self, CallbackDataCommon, Event, EventAlterables},
|
||||
event::{self, CallbackDataCommon, Event, EventAlterables, StyleSetRequest},
|
||||
globals::WguiGlobals,
|
||||
sound::WguiSoundType,
|
||||
task::Tasks,
|
||||
|
|
@ -149,6 +149,7 @@ pub type LayoutDispatchFunc = Box<dyn FnOnce(&mut CallbackDataCommon) -> anyhow:
|
|||
pub enum LayoutTask {
|
||||
RemoveWidget(WidgetID),
|
||||
SetWidgetStyle(WidgetID, event::StyleSetRequest),
|
||||
SetWidgetVisible(WidgetID, bool), // if true, sets Display to Flex; None, otherwise
|
||||
ModifyLayoutState(LayoutModifyStateFunc),
|
||||
PlaySound(WguiSoundType),
|
||||
Dispatch(LayoutDispatchFunc),
|
||||
|
|
@ -746,6 +747,16 @@ impl Layout {
|
|||
LayoutTask::SetWidgetStyle(widget_id, style_request) => {
|
||||
self.set_style_request(widget_id, &style_request);
|
||||
}
|
||||
LayoutTask::SetWidgetVisible(widget_id, visible) => {
|
||||
self.set_style_request(
|
||||
widget_id,
|
||||
&StyleSetRequest::Display(if visible {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
}),
|
||||
);
|
||||
}
|
||||
LayoutTask::SetFocus(weak) => {
|
||||
if let Some(c) = weak.upgrade() {
|
||||
self.set_focus(Some(&components::Component(c)))?;
|
||||
|
|
|
|||
|
|
@ -36,10 +36,8 @@ pub fn parse_widget_label<'a>(
|
|||
params.content = Translation::from_raw_text(value);
|
||||
}
|
||||
}
|
||||
"translation" => {
|
||||
if !value.is_empty() {
|
||||
params.content = Translation::from_translation_key(value);
|
||||
}
|
||||
"translation" if !value.is_empty() => {
|
||||
params.content = Translation::from_translation_key(value);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub enum WlxFrame {
|
|||
Dmabuf(DmabufFrame),
|
||||
MemFd(MemFdFrame),
|
||||
MemPtr(MemPtrFrame),
|
||||
Implicit,
|
||||
Implicit(Transform),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -267,7 +267,8 @@ where
|
|||
// copy_with_damage seems to not work here
|
||||
proxy.copy(&wl_buffer);
|
||||
|
||||
frame_buffer = Some((WlxFrame::Implicit, BufData::Dma { wl_buffer }));
|
||||
frame_buffer =
|
||||
Some((WlxFrame::Implicit(transform), BufData::Dma { wl_buffer }));
|
||||
} else if let Some(ScreenCopyEvent::Buffer {
|
||||
shm_format,
|
||||
width,
|
||||
|
|
|
|||
|
|
@ -165,6 +165,10 @@ const fn def_point3() -> f32 {
|
|||
0.3
|
||||
}
|
||||
|
||||
const fn def_zero() -> f32 {
|
||||
0.0
|
||||
}
|
||||
|
||||
const fn def_osc_port() -> u16 {
|
||||
9000
|
||||
}
|
||||
|
|
@ -273,6 +277,9 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_false")]
|
||||
pub double_cursor_fix: bool,
|
||||
|
||||
#[serde(default = "def_true")]
|
||||
pub enable_watch: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
pub sets_on_watch: bool,
|
||||
|
||||
|
|
@ -336,6 +343,24 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_false")]
|
||||
pub space_rotate_unlocked: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
pub space_gravity_enabled: bool,
|
||||
|
||||
#[serde(default = "def_one")]
|
||||
pub space_gravity_gravity: f32,
|
||||
|
||||
#[serde(default = "def_one")]
|
||||
pub space_gravity_damping: f32,
|
||||
|
||||
#[serde(default = "def_one")]
|
||||
pub space_gravity_fling_strength: f32,
|
||||
|
||||
#[serde(default = "def_one")]
|
||||
pub space_gravity_ground_friction: f32,
|
||||
|
||||
#[serde(default = "def_zero")]
|
||||
pub space_gravity_floor_height: f32,
|
||||
|
||||
#[serde(default)]
|
||||
pub alt_click_down: Vec<String>,
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue