mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-08-02 22:29:01 +00:00
feat: show steam launch options on start; rename openovr to opencomposite; fallback for selected profile
This commit is contained in:
parent
f373b725b4
commit
7da1f6f7ae
7 changed files with 141 additions and 44 deletions
|
@ -13,7 +13,7 @@ relm4 = { version = "0.6.0", features = [
|
||||||
] }
|
] }
|
||||||
relm4-components = "0.6.0"
|
relm4-components = "0.6.0"
|
||||||
relm4-icons = { version = "0.6.0", features = [
|
relm4-icons = { version = "0.6.0", features = [
|
||||||
"menu", "loupe"
|
"menu", "loupe", "copy"
|
||||||
] }
|
] }
|
||||||
serde = { version = "1.0.163", features = [
|
serde = { version = "1.0.163", features = [
|
||||||
"derive"
|
"derive"
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn config_file_path() -> String {
|
||||||
fn default_config() -> Config {
|
fn default_config() -> Config {
|
||||||
Config {
|
Config {
|
||||||
// TODO: handle first start with no profile selected
|
// TODO: handle first start with no profile selected
|
||||||
selected_profile_name: "Demo profile".to_string(),
|
selected_profile_name: "".to_string(),
|
||||||
debug_view_enabled: false,
|
debug_view_enabled: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::file_utils::get_writer;
|
||||||
pub struct Profile {
|
pub struct Profile {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub monado_path: String,
|
pub monado_path: String,
|
||||||
pub openovr_path: String,
|
pub opencomposite_path: String,
|
||||||
pub libsurvive_path: Option<String>,
|
pub libsurvive_path: Option<String>,
|
||||||
pub basalt_path: Option<String>,
|
pub basalt_path: Option<String>,
|
||||||
pub mercury_path: Option<String>,
|
pub mercury_path: Option<String>,
|
||||||
|
@ -26,6 +26,16 @@ impl Display for Profile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Profile {
|
||||||
|
pub fn get_steam_launch_options(&self) -> String {
|
||||||
|
let mut opts = vec![];
|
||||||
|
opts.push(format!("XR_RUNTIME_JSON={prefix}/share/openxr/1/openxr_monado.json", prefix = self.prefix));
|
||||||
|
opts.push(format!("PRESSURE_VESSEL_FILESYSTEMS_RW=$XDG_RUNTIME_DIR/monado_comp_ipc"));
|
||||||
|
opts.push("%command%".into());
|
||||||
|
opts.join(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_profile(path: &String) -> Profile {
|
pub fn load_profile(path: &String) -> Profile {
|
||||||
let file = File::open(path).expect_dialog("Unable to open profile");
|
let file = File::open(path).expect_dialog("Unable to open profile");
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
|
@ -48,7 +58,7 @@ mod tests {
|
||||||
let profile = load_profile(&"./test/files/profile.json".to_string());
|
let profile = load_profile(&"./test/files/profile.json".to_string());
|
||||||
assert_eq!(profile.name, "Demo profile");
|
assert_eq!(profile.name, "Demo profile");
|
||||||
assert_eq!(profile.monado_path, "/home/user/monado");
|
assert_eq!(profile.monado_path, "/home/user/monado");
|
||||||
assert_eq!(profile.openovr_path, "/home/user/openovr");
|
assert_eq!(profile.opencomposite_path, "/home/user/opencomposite");
|
||||||
assert_eq!(profile.prefix, "/home/user/rex2prefix");
|
assert_eq!(profile.prefix, "/home/user/rex2prefix");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
profile.libsurvive_path.as_deref(),
|
profile.libsurvive_path.as_deref(),
|
||||||
|
@ -76,7 +86,7 @@ mod tests {
|
||||||
let p = Profile {
|
let p = Profile {
|
||||||
name: "Demo profile".into(),
|
name: "Demo profile".into(),
|
||||||
monado_path: String::from("/home/user/monado"),
|
monado_path: String::from("/home/user/monado"),
|
||||||
openovr_path: String::from("/home/user/openovr"),
|
opencomposite_path: String::from("/home/user/opencomposite"),
|
||||||
libsurvive_path: Some(String::from("/home/user/libsurvive")),
|
libsurvive_path: Some(String::from("/home/user/libsurvive")),
|
||||||
basalt_path: None,
|
basalt_path: None,
|
||||||
mercury_path: None,
|
mercury_path: None,
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub fn valve_index_profile() -> Profile {
|
||||||
Profile {
|
Profile {
|
||||||
name: format!("Valve Index - {name} Default", name = APP_NAME),
|
name: format!("Valve Index - {name} Default", name = APP_NAME),
|
||||||
monado_path: format!("{data}/monado", data = data_dir),
|
monado_path: format!("{data}/monado", data = data_dir),
|
||||||
openovr_path: format!("{data}/openovr", data = data_dir),
|
opencomposite_path: format!("{data}/opencomposite", data = data_dir),
|
||||||
libsurvive_path: Some(format!("{data}/libsurvive", data = data_dir)),
|
libsurvive_path: Some(format!("{data}/libsurvive", data = data_dir)),
|
||||||
basalt_path: None,
|
basalt_path: None,
|
||||||
mercury_path: None,
|
mercury_path: None,
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use std::time::Duration;
|
use super::about_dialog::AboutDialog;
|
||||||
|
use super::build_window::BuildWindow;
|
||||||
|
use super::debug_view::{DebugView, DebugViewMsg};
|
||||||
|
use super::main_view::MainViewMsg;
|
||||||
use crate::builders::build_libsurvive::get_build_libsurvive_runner;
|
use crate::builders::build_libsurvive::get_build_libsurvive_runner;
|
||||||
use crate::builders::build_monado::get_build_monado_runner;
|
use crate::builders::build_monado::get_build_monado_runner;
|
||||||
|
use crate::builders::build_opencomposite::get_build_opencomposite_runner;
|
||||||
use crate::config::{get_config, save_config, Config};
|
use crate::config::{get_config, save_config, Config};
|
||||||
use crate::constants::APP_NAME;
|
use crate::constants::APP_NAME;
|
||||||
use crate::dependencies::libsurvive_deps::get_missing_libsurvive_deps;
|
use crate::dependencies::libsurvive_deps::get_missing_libsurvive_deps;
|
||||||
use crate::dependencies::monado_deps::{check_monado_deps, get_missing_monado_deps};
|
use crate::dependencies::monado_deps::get_missing_monado_deps;
|
||||||
use crate::profile::Profile;
|
use crate::profile::Profile;
|
||||||
use crate::profiles::valve_index::valve_index_profile;
|
use crate::profiles::valve_index::valve_index_profile;
|
||||||
use crate::runner::{Runner, RunnerStatus};
|
use crate::runner::{Runner, RunnerStatus};
|
||||||
|
@ -20,12 +23,7 @@ use relm4::adw::traits::MessageDialogExt;
|
||||||
use relm4::gtk::glib;
|
use relm4::gtk::glib;
|
||||||
use relm4::{new_action_group, new_stateful_action, new_stateless_action, prelude::*};
|
use relm4::{new_action_group, new_stateful_action, new_stateless_action, prelude::*};
|
||||||
use relm4::{ComponentParts, ComponentSender, SimpleComponent};
|
use relm4::{ComponentParts, ComponentSender, SimpleComponent};
|
||||||
use relm4_components::alert::{Alert, AlertSettings};
|
use std::time::Duration;
|
||||||
|
|
||||||
use super::about_dialog::AboutDialog;
|
|
||||||
use super::build_window::BuildWindow;
|
|
||||||
use super::debug_view::{DebugView, DebugViewMsg};
|
|
||||||
use super::main_view::MainViewMsg;
|
|
||||||
|
|
||||||
#[tracker::track]
|
#[tracker::track]
|
||||||
pub struct App {
|
pub struct App {
|
||||||
|
@ -74,8 +72,10 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_selected_profile(&self) -> &Profile {
|
pub fn get_selected_profile(&self) -> &Profile {
|
||||||
self.get_profile_by_name(&self.config.selected_profile_name)
|
match self.get_profile_by_name(&self.config.selected_profile_name) {
|
||||||
.expect_dialog("Could not find selected profile")
|
Some(profile) => profile,
|
||||||
|
None => self.profiles.get(0).expect_dialog("No profiles found"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_monado(&mut self) {
|
pub fn start_monado(&mut self) {
|
||||||
|
@ -152,7 +152,7 @@ impl SimpleComponent for App {
|
||||||
self.build_window
|
self.build_window
|
||||||
.sender()
|
.sender()
|
||||||
.emit(BuildWindowMsg::UpdateContent(pipeline.get_log()));
|
.emit(BuildWindowMsg::UpdateContent(pipeline.get_log()));
|
||||||
},
|
}
|
||||||
false => {
|
false => {
|
||||||
self.build_window
|
self.build_window
|
||||||
.sender()
|
.sender()
|
||||||
|
@ -181,6 +181,11 @@ impl SimpleComponent for App {
|
||||||
self.main_view
|
self.main_view
|
||||||
.sender()
|
.sender()
|
||||||
.emit(MainViewMsg::MonadoActiveChanged(true));
|
.emit(MainViewMsg::MonadoActiveChanged(true));
|
||||||
|
self.main_view
|
||||||
|
.sender()
|
||||||
|
.emit(MainViewMsg::SteamLaunchOptionsChanged(
|
||||||
|
self.get_selected_profile().get_steam_launch_options(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Some(runner) => match runner.status() {
|
Some(runner) => match runner.status() {
|
||||||
RunnerStatus::Running => {
|
RunnerStatus::Running => {
|
||||||
|
@ -217,6 +222,8 @@ impl SimpleComponent for App {
|
||||||
// runners.push(get_build_mercury_runner(profile.clone()));
|
// runners.push(get_build_mercury_runner(profile.clone()));
|
||||||
// }
|
// }
|
||||||
runners.push(get_build_monado_runner(profile.clone()));
|
runners.push(get_build_monado_runner(profile.clone()));
|
||||||
|
// no listed deps for opencomp
|
||||||
|
runners.push(get_build_opencomposite_runner(profile.clone()));
|
||||||
if !missing_deps.is_empty() {
|
if !missing_deps.is_empty() {
|
||||||
self.dependencies_dialog.set_body(
|
self.dependencies_dialog.set_body(
|
||||||
missing_deps
|
missing_deps
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
use gtk::prelude::*;
|
|
||||||
use relm4::prelude::*;
|
|
||||||
use relm4::{SimpleComponent, ComponentSender, ComponentParts};
|
|
||||||
use relm4_icons::icon_name;
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::constants::APP_NAME;
|
use crate::constants::APP_NAME;
|
||||||
use crate::ui::app::{AboutAction, DebugViewToggleAction, BuildProfileAction};
|
use crate::ui::app::{AboutAction, BuildProfileAction, DebugViewToggleAction};
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use relm4::prelude::*;
|
||||||
|
use relm4::{ComponentParts, ComponentSender, SimpleComponent};
|
||||||
|
use relm4_icons::icon_name;
|
||||||
|
|
||||||
#[tracker::track]
|
#[tracker::track]
|
||||||
pub struct MainView {
|
pub struct MainView {
|
||||||
monado_active: bool,
|
monado_active: bool,
|
||||||
enable_debug_view: bool,
|
enable_debug_view: bool,
|
||||||
profile_names: Vec<String>,
|
profile_names: Vec<String>,
|
||||||
|
steam_launch_options: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -19,6 +20,7 @@ pub enum MainViewMsg {
|
||||||
MonadoActiveChanged(bool),
|
MonadoActiveChanged(bool),
|
||||||
EnableDebugViewChanged(bool),
|
EnableDebugViewChanged(bool),
|
||||||
UpdateProfileNames(Vec<String>),
|
UpdateProfileNames(Vec<String>),
|
||||||
|
SteamLaunchOptionsChanged(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -84,26 +86,98 @@ impl SimpleComponent for MainView {
|
||||||
set_show_end_title_buttons: !model.enable_debug_view,
|
set_show_end_title_buttons: !model.enable_debug_view,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gtk::Box {
|
gtk::ScrolledWindow {
|
||||||
set_spacing: 12,
|
set_hscrollbar_policy: gtk::PolicyType::Never,
|
||||||
set_margin_all: 12,
|
set_hexpand: true,
|
||||||
gtk::Button {
|
set_vexpand: true,
|
||||||
add_css_class: "pill",
|
gtk::Box {
|
||||||
add_css_class: "suggested-action",
|
set_spacing: 12,
|
||||||
add_css_class: "destructive-action",
|
set_margin_top: 12,
|
||||||
set_hexpand: true,
|
set_margin_bottom: 12,
|
||||||
set_halign: gtk::Align::Center,
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
#[track = "model.changed(MainView::monado_active())"]
|
gtk::Button {
|
||||||
set_class_active: ("suggested-action", !model.monado_active),
|
add_css_class: "pill",
|
||||||
#[track = "model.changed(MainView::monado_active())"]
|
add_css_class: "suggested-action",
|
||||||
set_label: match model.monado_active {
|
add_css_class: "destructive-action",
|
||||||
true => "Stop",
|
set_hexpand: true,
|
||||||
false => "Start",
|
set_halign: gtk::Align::Center,
|
||||||
|
#[track = "model.changed(MainView::monado_active())"]
|
||||||
|
set_class_active: ("suggested-action", !model.monado_active),
|
||||||
|
#[track = "model.changed(MainView::monado_active())"]
|
||||||
|
set_label: match model.monado_active {
|
||||||
|
true => "Stop",
|
||||||
|
false => "Start",
|
||||||
|
},
|
||||||
|
connect_clicked[sender] => move |_| {
|
||||||
|
sender.input(MainViewMsg::StartStopClicked)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
connect_clicked[sender] => move |_| {
|
gtk::Box {
|
||||||
sender.input(MainViewMsg::StartStopClicked)
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_hexpand: true,
|
||||||
|
set_vexpand: false,
|
||||||
|
set_spacing: 12,
|
||||||
|
set_margin_top: 12,
|
||||||
|
set_margin_bottom: 12,
|
||||||
|
#[track = "model.changed(MainView::monado_active())"]
|
||||||
|
set_visible: model.monado_active,
|
||||||
|
gtk::Separator {
|
||||||
|
set_orientation: gtk::Orientation::Horizontal,
|
||||||
|
set_hexpand: true,
|
||||||
|
},
|
||||||
|
gtk::Label {
|
||||||
|
add_css_class: "heading",
|
||||||
|
set_hexpand: true,
|
||||||
|
set_xalign: 0.0,
|
||||||
|
set_margin_start: 12,
|
||||||
|
set_margin_end: 12,
|
||||||
|
set_label: "Steam Launch Options",
|
||||||
|
set_wrap: true,
|
||||||
|
set_wrap_mode: gtk::pango::WrapMode::Word,
|
||||||
|
},
|
||||||
|
gtk::Label {
|
||||||
|
add_css_class: "dim-label",
|
||||||
|
set_hexpand: true,
|
||||||
|
set_xalign: 0.0,
|
||||||
|
set_margin_start: 12,
|
||||||
|
set_margin_end: 12,
|
||||||
|
set_label: "Set this string in the launch options of Steam games, so that they can pick up Monado and OpenOVR correctly",
|
||||||
|
set_wrap: true,
|
||||||
|
set_wrap_mode: gtk::pango::WrapMode::Word,
|
||||||
|
},
|
||||||
|
gtk::Box {
|
||||||
|
set_margin_start: 12,
|
||||||
|
set_margin_end: 12,
|
||||||
|
set_orientation: gtk::Orientation::Horizontal,
|
||||||
|
set_spacing: 6,
|
||||||
|
gtk::TextView {
|
||||||
|
add_css_class: "card",
|
||||||
|
set_hexpand: true,
|
||||||
|
set_vexpand: false,
|
||||||
|
set_monospace: true,
|
||||||
|
set_editable: false,
|
||||||
|
set_wrap_mode: gtk::WrapMode::Word,
|
||||||
|
set_left_margin: 6,
|
||||||
|
set_right_margin: 6,
|
||||||
|
set_top_margin: 6,
|
||||||
|
set_bottom_margin: 6,
|
||||||
|
set_size_request: (-1, 150),
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_buffer: cmdbuf = >k::TextBuffer {
|
||||||
|
#[track = "model.changed(MainView::steam_launch_options())"]
|
||||||
|
set_text: model.steam_launch_options.as_str(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
gtk::Button {
|
||||||
|
add_css_class: "flat",
|
||||||
|
add_css_class: "circular",
|
||||||
|
set_icon_name: icon_name::COPY,
|
||||||
|
set_vexpand: false,
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +188,7 @@ impl SimpleComponent for MainView {
|
||||||
match message {
|
match message {
|
||||||
MainViewMsg::StartStopClicked => {
|
MainViewMsg::StartStopClicked => {
|
||||||
sender.output(MainViewOutMsg::DoStartStopMonado);
|
sender.output(MainViewOutMsg::DoStartStopMonado);
|
||||||
},
|
}
|
||||||
MainViewMsg::MonadoActiveChanged(active) => {
|
MainViewMsg::MonadoActiveChanged(active) => {
|
||||||
self.set_monado_active(active);
|
self.set_monado_active(active);
|
||||||
}
|
}
|
||||||
|
@ -124,14 +198,20 @@ impl SimpleComponent for MainView {
|
||||||
MainViewMsg::UpdateProfileNames(names) => {
|
MainViewMsg::UpdateProfileNames(names) => {
|
||||||
self.set_profile_names(names);
|
self.set_profile_names(names);
|
||||||
}
|
}
|
||||||
|
MainViewMsg::SteamLaunchOptionsChanged(lo) => self.set_steam_launch_options(lo),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(init: Self::Init, root: &Self::Root, sender: ComponentSender<Self>) -> ComponentParts<Self> {
|
fn init(
|
||||||
|
init: Self::Init,
|
||||||
|
root: &Self::Root,
|
||||||
|
sender: ComponentSender<Self>,
|
||||||
|
) -> ComponentParts<Self> {
|
||||||
let model = MainView {
|
let model = MainView {
|
||||||
monado_active: false,
|
monado_active: false,
|
||||||
enable_debug_view: init.config.debug_view_enabled,
|
enable_debug_view: init.config.debug_view_enabled,
|
||||||
profile_names: vec![],
|
profile_names: vec![],
|
||||||
|
steam_launch_options: "".into(),
|
||||||
tracker: 0,
|
tracker: 0,
|
||||||
};
|
};
|
||||||
let widgets = view_output!();
|
let widgets = view_output!();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "Demo profile",
|
"name": "Demo profile",
|
||||||
"monado_path": "/home/user/monado",
|
"monado_path": "/home/user/monado",
|
||||||
"openovr_path": "/home/user/openovr",
|
"opencomposite_path": "/home/user/opencomposite",
|
||||||
"libsurvive_path": "/home/user/libsurvive",
|
"libsurvive_path": "/home/user/libsurvive",
|
||||||
"basalt_path": null,
|
"basalt_path": null,
|
||||||
"mercury_path": null,
|
"mercury_path": null,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue