feat(ui): dropdown rolldown animation, sound in replay, square buttons, full QoL keybinds, and monospace font support
This commit is contained in:
parent
6e114cb3ff
commit
20f9773080
5 changed files with 410 additions and 168 deletions
BIN
assets/fonts/AdwaitaMono-Regular.ttf
Normal file
BIN
assets/fonts/AdwaitaMono-Regular.ttf
Normal file
Binary file not shown.
|
|
@ -350,6 +350,26 @@ fn handle_screenshot() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_mute_mic() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
let mut cfg = scythe::config::ScytheConfig::load();
|
||||||
|
let is_muted = cfg.mic_volume < 0.05;
|
||||||
|
cfg.mic_volume = if is_muted { 0.60 } else { 0.0 };
|
||||||
|
let _ = cfg.save();
|
||||||
|
scythe::config::ScytheConfig::notify_daemon_reload();
|
||||||
|
show_shadowplay_toast("MICROPHONE", if is_muted { "Unmuted" } else { "Muted" }, ToastIcon::Info);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_mute_sys() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
let mut cfg = scythe::config::ScytheConfig::load();
|
||||||
|
let is_muted = cfg.system_volume < 0.05;
|
||||||
|
cfg.system_volume = if is_muted { 1.00 } else { 0.0 };
|
||||||
|
let _ = cfg.save();
|
||||||
|
scythe::config::ScytheConfig::notify_daemon_reload();
|
||||||
|
show_shadowplay_toast("SYSTEM AUDIO", if is_muted { "Unmuted" } else { "Muted" }, ToastIcon::Info);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_toggle_streaming() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
fn handle_toggle_streaming() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
ensure_daemon_running();
|
ensure_daemon_running();
|
||||||
let cfg = scythe::config::ScytheConfig::load();
|
let cfg = scythe::config::ScytheConfig::load();
|
||||||
|
|
@ -409,6 +429,15 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
"--screenshot" => {
|
"--screenshot" => {
|
||||||
return handle_screenshot();
|
return handle_screenshot();
|
||||||
}
|
}
|
||||||
|
"--mute-mic" => {
|
||||||
|
return handle_mute_mic();
|
||||||
|
}
|
||||||
|
"--mute-sys" => {
|
||||||
|
return handle_mute_sys();
|
||||||
|
}
|
||||||
|
"--pause" => {
|
||||||
|
return handle_toggle_recording();
|
||||||
|
}
|
||||||
"--toast" => {
|
"--toast" => {
|
||||||
let title = args.get(2).map(|s| s.as_str()).unwrap_or("SCYTHE");
|
let title = args.get(2).map(|s| s.as_str()).unwrap_or("SCYTHE");
|
||||||
let subtitle = args.get(3).map(|s| s.as_str()).unwrap_or("");
|
let subtitle = args.get(3).map(|s| s.as_str()).unwrap_or("");
|
||||||
|
|
@ -570,8 +599,11 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
menu: Option<u32>,
|
menu: Option<u32>,
|
||||||
save: Option<u32>,
|
save: Option<u32>,
|
||||||
rec: Option<u32>,
|
rec: Option<u32>,
|
||||||
|
pause: Option<u32>,
|
||||||
cur: Option<u32>,
|
cur: Option<u32>,
|
||||||
shot: Option<u32>,
|
shot: Option<u32>,
|
||||||
|
mute_mic: Option<u32>,
|
||||||
|
mute_sys: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut current_config = scythe::config::ScytheConfig::load();
|
let mut current_config = scythe::config::ScytheConfig::load();
|
||||||
|
|
@ -585,8 +617,11 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let m_menu = scythe::hotkey::parse_hotkey(&cfg.menu_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::ALT), Code::KeyZ)));
|
let m_menu = scythe::hotkey::parse_hotkey(&cfg.menu_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::ALT), Code::KeyZ)));
|
||||||
let m_save = scythe::hotkey::parse_hotkey(&cfg.save_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyR)));
|
let m_save = scythe::hotkey::parse_hotkey(&cfg.save_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyR)));
|
||||||
let m_rec = scythe::hotkey::parse_hotkey(&cfg.record_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::F9)));
|
let m_rec = scythe::hotkey::parse_hotkey(&cfg.record_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::F9)));
|
||||||
|
let m_pause = scythe::hotkey::parse_hotkey(&cfg.pause_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::F8)));
|
||||||
let m_cur = scythe::hotkey::parse_hotkey(&cfg.cursor_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::F10)));
|
let m_cur = scythe::hotkey::parse_hotkey(&cfg.cursor_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::F10)));
|
||||||
let m_shot = scythe::hotkey::parse_hotkey(&cfg.screenshot_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyS)));
|
let m_shot = scythe::hotkey::parse_hotkey(&cfg.screenshot_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyS)));
|
||||||
|
let m_mute_mic = scythe::hotkey::parse_hotkey(&cfg.mute_mic_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyM)));
|
||||||
|
let m_mute_sys = scythe::hotkey::parse_hotkey(&cfg.mute_sys_hotkey).or_else(|| Some(HotKey::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyN)));
|
||||||
|
|
||||||
let mut ids = RegisteredIds::default();
|
let mut ids = RegisteredIds::default();
|
||||||
|
|
||||||
|
|
@ -606,6 +641,11 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let _ = mgr.register(hk);
|
let _ = mgr.register(hk);
|
||||||
reg.push(hk);
|
reg.push(hk);
|
||||||
}
|
}
|
||||||
|
if let Some(hk) = m_pause {
|
||||||
|
ids.pause = Some(hk.id());
|
||||||
|
let _ = mgr.register(hk);
|
||||||
|
reg.push(hk);
|
||||||
|
}
|
||||||
if let Some(hk) = m_cur {
|
if let Some(hk) = m_cur {
|
||||||
ids.cur = Some(hk.id());
|
ids.cur = Some(hk.id());
|
||||||
let _ = mgr.register(hk);
|
let _ = mgr.register(hk);
|
||||||
|
|
@ -616,13 +656,23 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let _ = mgr.register(hk);
|
let _ = mgr.register(hk);
|
||||||
reg.push(hk);
|
reg.push(hk);
|
||||||
}
|
}
|
||||||
|
if let Some(hk) = m_mute_mic {
|
||||||
|
ids.mute_mic = Some(hk.id());
|
||||||
|
let _ = mgr.register(hk);
|
||||||
|
reg.push(hk);
|
||||||
|
}
|
||||||
|
if let Some(hk) = m_mute_sys {
|
||||||
|
ids.mute_sys = Some(hk.id());
|
||||||
|
let _ = mgr.register(hk);
|
||||||
|
reg.push(hk);
|
||||||
|
}
|
||||||
ids
|
ids
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut current_ids = register_all(&manager, ¤t_config, &mut registered_hotkeys);
|
let mut current_ids = register_all(&manager, ¤t_config, &mut registered_hotkeys);
|
||||||
|
|
||||||
println!("Listening for global hotkeys (Overlay: {}, Replay: {}, Record: {}, Cursor: {}, Screenshot: {})...",
|
println!("Listening for global hotkeys (Overlay: {}, Replay: {}, Record: {}, Screenshot: {})...",
|
||||||
current_config.menu_hotkey, current_config.save_hotkey, current_config.record_hotkey, current_config.cursor_hotkey, current_config.screenshot_hotkey);
|
current_config.menu_hotkey, current_config.save_hotkey, current_config.record_hotkey, current_config.screenshot_hotkey);
|
||||||
|
|
||||||
let receiver = GlobalHotKeyEvent::receiver();
|
let receiver = GlobalHotKeyEvent::receiver();
|
||||||
let mut last_config_check = std::time::Instant::now();
|
let mut last_config_check = std::time::Instant::now();
|
||||||
|
|
@ -646,8 +696,11 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
if new_cfg.menu_hotkey != current_config.menu_hotkey
|
if new_cfg.menu_hotkey != current_config.menu_hotkey
|
||||||
|| new_cfg.save_hotkey != current_config.save_hotkey
|
|| new_cfg.save_hotkey != current_config.save_hotkey
|
||||||
|| new_cfg.record_hotkey != current_config.record_hotkey
|
|| new_cfg.record_hotkey != current_config.record_hotkey
|
||||||
|
|| new_cfg.pause_hotkey != current_config.pause_hotkey
|
||||||
|| new_cfg.cursor_hotkey != current_config.cursor_hotkey
|
|| new_cfg.cursor_hotkey != current_config.cursor_hotkey
|
||||||
|| new_cfg.screenshot_hotkey != current_config.screenshot_hotkey
|
|| new_cfg.screenshot_hotkey != current_config.screenshot_hotkey
|
||||||
|
|| new_cfg.mute_mic_hotkey != current_config.mute_mic_hotkey
|
||||||
|
|| new_cfg.mute_sys_hotkey != current_config.mute_sys_hotkey
|
||||||
{
|
{
|
||||||
current_config = new_cfg;
|
current_config = new_cfg;
|
||||||
current_ids = register_all(&manager, ¤t_config, &mut registered_hotkeys);
|
current_ids = register_all(&manager, ¤t_config, &mut registered_hotkeys);
|
||||||
|
|
@ -671,6 +724,10 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
std::thread::spawn(|| {
|
std::thread::spawn(|| {
|
||||||
let _ = handle_toggle_recording();
|
let _ = handle_toggle_recording();
|
||||||
});
|
});
|
||||||
|
} else if Some(event.id) == current_ids.pause {
|
||||||
|
std::thread::spawn(|| {
|
||||||
|
let _ = handle_toggle_recording();
|
||||||
|
});
|
||||||
} else if Some(event.id) == current_ids.cur {
|
} else if Some(event.id) == current_ids.cur {
|
||||||
std::thread::spawn(|| {
|
std::thread::spawn(|| {
|
||||||
let _ = handle_toggle_cursor();
|
let _ = handle_toggle_cursor();
|
||||||
|
|
@ -679,6 +736,14 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
std::thread::spawn(|| {
|
std::thread::spawn(|| {
|
||||||
let _ = handle_screenshot();
|
let _ = handle_screenshot();
|
||||||
});
|
});
|
||||||
|
} else if Some(event.id) == current_ids.mute_mic {
|
||||||
|
std::thread::spawn(|| {
|
||||||
|
let _ = handle_mute_mic();
|
||||||
|
});
|
||||||
|
} else if Some(event.id) == current_ids.mute_sys {
|
||||||
|
std::thread::spawn(|| {
|
||||||
|
let _ = handle_mute_sys();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,11 @@ fn default_replay_storage() -> String { "ram".to_string() }
|
||||||
fn default_container_format() -> String { "mp4".to_string() }
|
fn default_container_format() -> String { "mp4".to_string() }
|
||||||
fn default_res_w() -> u32 { 1920 }
|
fn default_res_w() -> u32 { 1920 }
|
||||||
fn default_res_h() -> u32 { 1080 }
|
fn default_res_h() -> u32 { 1080 }
|
||||||
|
fn default_screenshot_quality() -> u32 { 90 }
|
||||||
|
fn default_screenshot_preset() -> String { "balanced".to_string() }
|
||||||
|
fn default_pause_hotkey() -> String { "Ctrl+Shift+F8".to_string() }
|
||||||
|
fn default_mute_mic_hotkey() -> String { "Ctrl+Shift+M".to_string() }
|
||||||
|
fn default_mute_sys_hotkey() -> String { "Ctrl+Shift+N".to_string() }
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct ScytheConfig {
|
pub struct ScytheConfig {
|
||||||
|
|
@ -138,6 +143,19 @@ pub struct ScytheConfig {
|
||||||
pub autostart_on_game: bool,
|
pub autostart_on_game: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub autostart_power_only: bool,
|
pub autostart_power_only: bool,
|
||||||
|
|
||||||
|
#[serde(default = "default_screenshot_quality")]
|
||||||
|
pub screenshot_quality: u32,
|
||||||
|
#[serde(default = "default_screenshot_preset")]
|
||||||
|
pub screenshot_preset: String,
|
||||||
|
#[serde(default = "default_pause_hotkey")]
|
||||||
|
pub pause_hotkey: String,
|
||||||
|
#[serde(default = "default_mute_mic_hotkey")]
|
||||||
|
pub mute_mic_hotkey: String,
|
||||||
|
#[serde(default = "default_mute_sys_hotkey")]
|
||||||
|
pub mute_sys_hotkey: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub use_monospace_font: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type VrecConfig = ScytheConfig;
|
pub type VrecConfig = ScytheConfig;
|
||||||
|
|
@ -199,6 +217,13 @@ impl Default for ScytheConfig {
|
||||||
show_scroll_lock_led: false,
|
show_scroll_lock_led: false,
|
||||||
autostart_on_game: false,
|
autostart_on_game: false,
|
||||||
autostart_power_only: false,
|
autostart_power_only: false,
|
||||||
|
|
||||||
|
screenshot_quality: default_screenshot_quality(),
|
||||||
|
screenshot_preset: default_screenshot_preset(),
|
||||||
|
pause_hotkey: default_pause_hotkey(),
|
||||||
|
mute_mic_hotkey: default_mute_mic_hotkey(),
|
||||||
|
mute_sys_hotkey: default_mute_sys_hotkey(),
|
||||||
|
use_monospace_font: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -483,6 +508,13 @@ mod tests {
|
||||||
assert_eq!(parsed.screenshot_hotkey, "Ctrl+Shift+S");
|
assert_eq!(parsed.screenshot_hotkey, "Ctrl+Shift+S");
|
||||||
assert_eq!(parsed.screenshot_format, "png");
|
assert_eq!(parsed.screenshot_format, "png");
|
||||||
assert!(!parsed.screenshot_cursor);
|
assert!(!parsed.screenshot_cursor);
|
||||||
|
|
||||||
|
assert_eq!(parsed.screenshot_quality, 90);
|
||||||
|
assert_eq!(parsed.screenshot_preset, "balanced");
|
||||||
|
assert_eq!(parsed.pause_hotkey, "Ctrl+Shift+F8");
|
||||||
|
assert_eq!(parsed.mute_mic_hotkey, "Ctrl+Shift+M");
|
||||||
|
assert_eq!(parsed.mute_sys_hotkey, "Ctrl+Shift+N");
|
||||||
|
assert!(!parsed.use_monospace_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -182,8 +182,11 @@ pub fn register_hyprland_binds(config: &ScytheConfig) {
|
||||||
(&config.menu_hotkey, "scythe-ui --menu"),
|
(&config.menu_hotkey, "scythe-ui --menu"),
|
||||||
(&config.save_hotkey, "scythe-ui --save"),
|
(&config.save_hotkey, "scythe-ui --save"),
|
||||||
(&config.record_hotkey, "scythe-ui --record"),
|
(&config.record_hotkey, "scythe-ui --record"),
|
||||||
|
(&config.pause_hotkey, "scythe-ui --pause"),
|
||||||
(&config.cursor_hotkey, "scythe-ui --cursor"),
|
(&config.cursor_hotkey, "scythe-ui --cursor"),
|
||||||
(&config.screenshot_hotkey, "scythe-ui --screenshot"),
|
(&config.screenshot_hotkey, "scythe-ui --screenshot"),
|
||||||
|
(&config.mute_mic_hotkey, "scythe-ui --mute-mic"),
|
||||||
|
(&config.mute_sys_hotkey, "scythe-ui --mute-sys"),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (hotkey, cmd) in binds {
|
for (hotkey, cmd) in binds {
|
||||||
|
|
|
||||||
|
|
@ -199,19 +199,33 @@ pub enum KeybindAction {
|
||||||
Menu,
|
Menu,
|
||||||
SaveReplay,
|
SaveReplay,
|
||||||
ToggleRecord,
|
ToggleRecord,
|
||||||
|
PauseRecord,
|
||||||
|
Screenshot,
|
||||||
ToggleCursor,
|
ToggleCursor,
|
||||||
|
MuteMic,
|
||||||
|
MuteSystem,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_custom_fonts(ctx: &egui::Context) {
|
pub fn setup_custom_fonts(ctx: &egui::Context, use_monospace: bool) {
|
||||||
let mut fonts = egui::FontDefinitions::default();
|
let mut fonts = egui::FontDefinitions::default();
|
||||||
fonts.font_data.insert(
|
fonts.font_data.insert(
|
||||||
"modern_sans".to_owned(),
|
"modern_sans".to_owned(),
|
||||||
Arc::new(egui::FontData::from_static(include_bytes!("../assets/fonts/AdwaitaSans-Regular.ttf"))),
|
Arc::new(egui::FontData::from_static(include_bytes!("../assets/fonts/AdwaitaSans-Regular.ttf"))),
|
||||||
);
|
);
|
||||||
|
fonts.font_data.insert(
|
||||||
|
"modern_mono".to_owned(),
|
||||||
|
Arc::new(egui::FontData::from_static(include_bytes!("../assets/fonts/AdwaitaMono-Regular.ttf"))),
|
||||||
|
);
|
||||||
|
|
||||||
|
let primary = if use_monospace { "modern_mono" } else { "modern_sans" };
|
||||||
fonts.families
|
fonts.families
|
||||||
.entry(egui::FontFamily::Proportional)
|
.entry(egui::FontFamily::Proportional)
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(0, "modern_sans".to_owned());
|
.insert(0, primary.to_owned());
|
||||||
|
fonts.families
|
||||||
|
.entry(egui::FontFamily::Monospace)
|
||||||
|
.or_default()
|
||||||
|
.insert(0, "modern_mono".to_owned());
|
||||||
ctx.set_fonts(fonts);
|
ctx.set_fonts(fonts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1147,6 +1161,9 @@ pub struct ScytheOverlayApp {
|
||||||
pub show_scroll_lock_led: bool,
|
pub show_scroll_lock_led: bool,
|
||||||
pub autostart_on_game: bool,
|
pub autostart_on_game: bool,
|
||||||
pub autostart_power_only: bool,
|
pub autostart_power_only: bool,
|
||||||
|
pub screenshot_quality: u32,
|
||||||
|
pub screenshot_preset: String,
|
||||||
|
pub use_monospace_font: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
@ -1238,6 +1255,9 @@ impl ScytheOverlayApp {
|
||||||
let show_scroll_lock_led = config.show_scroll_lock_led;
|
let show_scroll_lock_led = config.show_scroll_lock_led;
|
||||||
let autostart_on_game = config.autostart_on_game;
|
let autostart_on_game = config.autostart_on_game;
|
||||||
let autostart_power_only = config.autostart_power_only;
|
let autostart_power_only = config.autostart_power_only;
|
||||||
|
let screenshot_quality = config.screenshot_quality;
|
||||||
|
let screenshot_preset = config.screenshot_preset.clone();
|
||||||
|
let use_monospace_font = config.use_monospace_font;
|
||||||
|
|
||||||
let update_status = Arc::new(std::sync::Mutex::new(crate::updater::UpdateStatus::Idle));
|
let update_status = Arc::new(std::sync::Mutex::new(crate::updater::UpdateStatus::Idle));
|
||||||
if auto_check_updates {
|
if auto_check_updates {
|
||||||
|
|
@ -1317,6 +1337,9 @@ impl ScytheOverlayApp {
|
||||||
show_scroll_lock_led,
|
show_scroll_lock_led,
|
||||||
autostart_on_game,
|
autostart_on_game,
|
||||||
autostart_power_only,
|
autostart_power_only,
|
||||||
|
screenshot_quality,
|
||||||
|
screenshot_preset,
|
||||||
|
use_monospace_font,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1366,6 +1389,9 @@ impl ScytheOverlayApp {
|
||||||
self.config.show_scroll_lock_led = self.show_scroll_lock_led;
|
self.config.show_scroll_lock_led = self.show_scroll_lock_led;
|
||||||
self.config.autostart_on_game = self.autostart_on_game;
|
self.config.autostart_on_game = self.autostart_on_game;
|
||||||
self.config.autostart_power_only = self.autostart_power_only;
|
self.config.autostart_power_only = self.autostart_power_only;
|
||||||
|
self.config.screenshot_quality = self.screenshot_quality;
|
||||||
|
self.config.screenshot_preset = self.screenshot_preset.clone();
|
||||||
|
self.config.use_monospace_font = self.use_monospace_font;
|
||||||
let _ = self.config.save();
|
let _ = self.config.save();
|
||||||
crate::hyprland_binds::register_hyprland_binds(&self.config);
|
crate::hyprland_binds::register_hyprland_binds(&self.config);
|
||||||
crate::config::ScytheConfig::notify_daemon_reload();
|
crate::config::ScytheConfig::notify_daemon_reload();
|
||||||
|
|
@ -1409,6 +1435,9 @@ impl ScytheOverlayApp {
|
||||||
self.show_scroll_lock_led = def.show_scroll_lock_led;
|
self.show_scroll_lock_led = def.show_scroll_lock_led;
|
||||||
self.autostart_on_game = def.autostart_on_game;
|
self.autostart_on_game = def.autostart_on_game;
|
||||||
self.autostart_power_only = def.autostart_power_only;
|
self.autostart_power_only = def.autostart_power_only;
|
||||||
|
self.screenshot_quality = def.screenshot_quality;
|
||||||
|
self.screenshot_preset = def.screenshot_preset;
|
||||||
|
self.use_monospace_font = def.use_monospace_font;
|
||||||
self.show_hud_notification("DEFAULTS", "Settings restored to defaults", crate::overlay::ToastIcon::Info);
|
self.show_hud_notification("DEFAULTS", "Settings restored to defaults", crate::overlay::ToastIcon::Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1834,21 +1863,35 @@ impl ScytheOverlayApp {
|
||||||
self.switch_view(ShadowPlayView::Settings(SettingsTab::General), ctx);
|
self.switch_view(ShadowPlayView::Settings(SettingsTab::General), ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dropdown menus floating beneath cards with sleek rounded frosted glass
|
// Dropdown menus with rolldown/swipe animation and smooth background blur
|
||||||
let item_h = 38.0_f32;
|
let item_h = 36.0_f32;
|
||||||
|
let anim_replay = ui.ctx().animate_bool(ui.make_persistent_id("anim_replay_dropdown"), self.replay_dropdown_open);
|
||||||
|
let anim_record = ui.ctx().animate_bool(ui.make_persistent_id("anim_record_dropdown"), self.record_dropdown_open);
|
||||||
|
let anim_stream = ui.ctx().animate_bool(ui.make_persistent_id("anim_stream_dropdown"), self.stream_dropdown_open);
|
||||||
|
|
||||||
|
if anim_replay > 0.001 || anim_record > 0.001 || anim_stream > 0.001 {
|
||||||
|
ctx.request_repaint();
|
||||||
|
}
|
||||||
|
|
||||||
// Instant Replay dropdown
|
// Instant Replay dropdown
|
||||||
if self.replay_dropdown_open {
|
if anim_replay > 0.001 {
|
||||||
let drop_y = card0_rect.bottom() + 6.0;
|
let ease = 1.0 - (1.0 - anim_replay).powi(3);
|
||||||
let total_h = item_h * 5.0;
|
let drop_y = card0_rect.bottom() + 4.0;
|
||||||
let frame_rect = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y), Vec2::new(card_w, total_h));
|
let full_h = item_h * 5.0;
|
||||||
|
let cur_h = full_h * ease;
|
||||||
|
let frame_rect = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y), Vec2::new(card_w, cur_h));
|
||||||
draw_dropdown_frame(ui.painter(), frame_rect, accent);
|
draw_dropdown_frame(ui.painter(), frame_rect, accent);
|
||||||
|
|
||||||
let r0 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y), Vec2::new(card_w, item_h));
|
let clip_rect = frame_rect;
|
||||||
let r1 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + item_h), Vec2::new(card_w, item_h));
|
ui.allocate_new_ui(egui::UiBuilder::new().max_rect(clip_rect), |ui| {
|
||||||
let r2 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + item_h * 2.0), Vec2::new(card_w, item_h));
|
ui.set_clip_rect(clip_rect);
|
||||||
let r3 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + item_h * 3.0), Vec2::new(card_w, item_h));
|
let slide_offset = (1.0 - ease) * -12.0;
|
||||||
let r4 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + item_h * 4.0), Vec2::new(card_w, item_h));
|
|
||||||
|
let r0 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
let r1 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + item_h + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
let r2 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + item_h * 2.0 + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
let r3 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + item_h * 3.0 + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
let r4 = egui::Rect::from_min_size(egui::pos2(card0_rect.left(), drop_y + item_h * 4.0 + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
|
||||||
let toggle_title = if is_replay_active { "Turn off" } else { "Turn on" };
|
let toggle_title = if is_replay_active { "Turn off" } else { "Turn on" };
|
||||||
let toggle_icon = if is_replay_active { tex_stop } else { tex_play };
|
let toggle_icon = if is_replay_active { tex_stop } else { tex_play };
|
||||||
|
|
@ -1897,18 +1940,26 @@ impl ScytheOverlayApp {
|
||||||
if render_dropdown_item(ui, r4, "Settings", None, tex_settings_xs, accent, true) {
|
if render_dropdown_item(ui, r4, "Settings", None, tex_settings_xs, accent, true) {
|
||||||
self.switch_view(ShadowPlayView::Settings(SettingsTab::Replay), ctx);
|
self.switch_view(ShadowPlayView::Settings(SettingsTab::Replay), ctx);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record dropdown
|
// Record dropdown
|
||||||
if self.record_dropdown_open {
|
if anim_record > 0.001 {
|
||||||
let drop_y = card1_rect.bottom() + 6.0;
|
let ease = 1.0 - (1.0 - anim_record).powi(3);
|
||||||
let total_h = item_h * 3.0;
|
let drop_y = card1_rect.bottom() + 4.0;
|
||||||
let frame_rect = egui::Rect::from_min_size(egui::pos2(card1_rect.left(), drop_y), Vec2::new(card_w, total_h));
|
let full_h = item_h * 3.0;
|
||||||
|
let cur_h = full_h * ease;
|
||||||
|
let frame_rect = egui::Rect::from_min_size(egui::pos2(card1_rect.left(), drop_y), Vec2::new(card_w, cur_h));
|
||||||
draw_dropdown_frame(ui.painter(), frame_rect, accent);
|
draw_dropdown_frame(ui.painter(), frame_rect, accent);
|
||||||
|
|
||||||
let r0 = egui::Rect::from_min_size(egui::pos2(card1_rect.left(), drop_y), Vec2::new(card_w, item_h));
|
let clip_rect = frame_rect;
|
||||||
let r1 = egui::Rect::from_min_size(egui::pos2(card1_rect.left(), drop_y + item_h), Vec2::new(card_w, item_h));
|
ui.allocate_new_ui(egui::UiBuilder::new().max_rect(clip_rect), |ui| {
|
||||||
let r2 = egui::Rect::from_min_size(egui::pos2(card1_rect.left(), drop_y + item_h * 2.0), Vec2::new(card_w, item_h));
|
ui.set_clip_rect(clip_rect);
|
||||||
|
let slide_offset = (1.0 - ease) * -12.0;
|
||||||
|
|
||||||
|
let r0 = egui::Rect::from_min_size(egui::pos2(card1_rect.left(), drop_y + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
let r1 = egui::Rect::from_min_size(egui::pos2(card1_rect.left(), drop_y + item_h + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
let r2 = egui::Rect::from_min_size(egui::pos2(card1_rect.left(), drop_y + item_h * 2.0 + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
|
||||||
let rec_toggle_title = if is_recording { "Stop Recording" } else { "Start Recording" };
|
let rec_toggle_title = if is_recording { "Stop Recording" } else { "Start Recording" };
|
||||||
let rec_toggle_icon = if is_recording { tex_stop } else { tex_play };
|
let rec_toggle_icon = if is_recording { tex_stop } else { tex_play };
|
||||||
|
|
@ -1924,7 +1975,8 @@ impl ScytheOverlayApp {
|
||||||
self.record_dropdown_open = false;
|
self.record_dropdown_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pause_hk_opt: Option<&str> = None;
|
let pause_hk = self.config.pause_hotkey.trim();
|
||||||
|
let pause_hk_opt = if pause_hk.is_empty() { None } else { Some(pause_hk) };
|
||||||
if render_dropdown_item(ui, r1, "Pause", pause_hk_opt, tex_pause, accent, false) {
|
if render_dropdown_item(ui, r1, "Pause", pause_hk_opt, tex_pause, accent, false) {
|
||||||
self.record_dropdown_open = false;
|
self.record_dropdown_open = false;
|
||||||
}
|
}
|
||||||
|
|
@ -1932,17 +1984,25 @@ impl ScytheOverlayApp {
|
||||||
if render_dropdown_item(ui, r2, "Settings", None, tex_settings_xs, accent, true) {
|
if render_dropdown_item(ui, r2, "Settings", None, tex_settings_xs, accent, true) {
|
||||||
self.switch_view(ShadowPlayView::Settings(SettingsTab::Record), ctx);
|
self.switch_view(ShadowPlayView::Settings(SettingsTab::Record), ctx);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Livestream dropdown
|
// Livestream dropdown
|
||||||
if self.stream_dropdown_open {
|
if anim_stream > 0.001 {
|
||||||
let drop_y = card2_rect.bottom() + 6.0;
|
let ease = 1.0 - (1.0 - anim_stream).powi(3);
|
||||||
let total_h = item_h * 2.0;
|
let drop_y = card2_rect.bottom() + 4.0;
|
||||||
let frame_rect = egui::Rect::from_min_size(egui::pos2(card2_rect.left(), drop_y), Vec2::new(card_w, total_h));
|
let full_h = item_h * 2.0;
|
||||||
|
let cur_h = full_h * ease;
|
||||||
|
let frame_rect = egui::Rect::from_min_size(egui::pos2(card2_rect.left(), drop_y), Vec2::new(card_w, cur_h));
|
||||||
draw_dropdown_frame(ui.painter(), frame_rect, accent);
|
draw_dropdown_frame(ui.painter(), frame_rect, accent);
|
||||||
|
|
||||||
let r0 = egui::Rect::from_min_size(egui::pos2(card2_rect.left(), drop_y), Vec2::new(card_w, item_h));
|
let clip_rect = frame_rect;
|
||||||
let r1 = egui::Rect::from_min_size(egui::pos2(card2_rect.left(), drop_y + item_h), Vec2::new(card_w, item_h));
|
ui.allocate_new_ui(egui::UiBuilder::new().max_rect(clip_rect), |ui| {
|
||||||
|
ui.set_clip_rect(clip_rect);
|
||||||
|
let slide_offset = (1.0 - ease) * -12.0;
|
||||||
|
|
||||||
|
let r0 = egui::Rect::from_min_size(egui::pos2(card2_rect.left(), drop_y + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
let r1 = egui::Rect::from_min_size(egui::pos2(card2_rect.left(), drop_y + item_h + slide_offset), Vec2::new(card_w, item_h));
|
||||||
|
|
||||||
let stream_toggle_title = if is_streaming { "Stop Streaming" } else { "Start Streaming" };
|
let stream_toggle_title = if is_streaming { "Stop Streaming" } else { "Start Streaming" };
|
||||||
let stream_toggle_icon = if is_streaming { tex_stop } else { tex_play };
|
let stream_toggle_icon = if is_streaming { tex_stop } else { tex_play };
|
||||||
|
|
@ -1964,8 +2024,10 @@ impl ScytheOverlayApp {
|
||||||
if render_dropdown_item(ui, r1, "Settings", None, tex_settings_xs, accent, true) {
|
if render_dropdown_item(ui, r1, "Settings", None, tex_settings_xs, accent, true) {
|
||||||
self.switch_view(ShadowPlayView::Settings(SettingsTab::Livestream), ctx);
|
self.switch_view(ShadowPlayView::Settings(SettingsTab::Livestream), ctx);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_settings_view(&mut self, ctx: &egui::Context, ui: &mut egui::Ui) {
|
fn render_settings_view(&mut self, ctx: &egui::Context, ui: &mut egui::Ui) {
|
||||||
let screen_w = ui.available_width();
|
let screen_w = ui.available_width();
|
||||||
let screen_h = ui.available_height();
|
let screen_h = ui.available_height();
|
||||||
|
|
@ -2281,6 +2343,49 @@ impl ScytheOverlayApp {
|
||||||
|
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
|
|
||||||
|
render_section_card(ui, "Audio", accent, |ui| {
|
||||||
|
ui.label(egui::RichText::new("Audio capture source mode:").size(11.5).color(Color32::from_rgb(180, 185, 190)));
|
||||||
|
ui.add_space(4.0);
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
let modes = [("system", "System Audio"), ("mic", "Microphone"), ("both", "Both"), ("muted", "Muted")];
|
||||||
|
for (idx, (_, m_label)) in modes.iter().enumerate() {
|
||||||
|
if squared_button(ui, m_label, self.audio_mode_idx == idx, accent) {
|
||||||
|
self.audio_mode_idx = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.add_space(8.0);
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(egui::RichText::new("Audio codec:").size(11.5).color(Color32::from_rgb(180, 185, 190)));
|
||||||
|
if squared_button(ui, "Opus (Recommended)", self.config.audio_codec == "opus", accent) {
|
||||||
|
self.config.audio_codec = "opus".to_string();
|
||||||
|
}
|
||||||
|
if squared_button(ui, "AAC", self.config.audio_codec == "aac", accent) {
|
||||||
|
self.config.audio_codec = "aac".to_string();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.add_space(8.0);
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(egui::RichText::new("Sys Vol:").size(11.5).color(Color32::WHITE));
|
||||||
|
let mut sv = self.system_volume_pct;
|
||||||
|
if ui.add(egui::Slider::new(&mut sv, 0..=150).suffix("%")).changed() {
|
||||||
|
self.system_volume_pct = sv;
|
||||||
|
}
|
||||||
|
ui.add_space(10.0);
|
||||||
|
ui.label(egui::RichText::new("Mic Vol:").size(11.5).color(Color32::WHITE));
|
||||||
|
let mut mv = self.mic_volume_pct;
|
||||||
|
if ui.add(egui::Slider::new(&mut mv, 0..=150).suffix("%")).changed() {
|
||||||
|
self.mic_volume_pct = mv;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ui.add_space(3.0);
|
||||||
|
render_vu_meter(ui, self.sys_vu, ui.available_width() - 8.0, 10.0, "SYS");
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.add_space(10.0);
|
||||||
|
|
||||||
render_section_card(ui, "Video parameters", accent, |ui| {
|
render_section_card(ui, "Video parameters", accent, |ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
|
|
@ -2343,21 +2448,22 @@ impl ScytheOverlayApp {
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
|
|
||||||
render_section_card(ui, "Autostart", accent, |ui| {
|
render_section_card(ui, "Autostart", accent, |ui| {
|
||||||
ui.horizontal(|ui| {
|
|
||||||
let neither = !self.autostart_replay && !self.autostart_on_game;
|
let neither = !self.autostart_replay && !self.autostart_on_game;
|
||||||
if squared_button(ui, "Don't turn on replay automatically", neither, accent) {
|
let btn_w = ui.available_width() - 8.0;
|
||||||
|
if squared_button_sized(ui, "Don't turn on replay automatically", neither, accent, Some(Vec2::new(btn_w, 26.0))) {
|
||||||
self.autostart_replay = false;
|
self.autostart_replay = false;
|
||||||
self.autostart_on_game = false;
|
self.autostart_on_game = false;
|
||||||
}
|
}
|
||||||
if squared_button(ui, "Turn on replay when this program starts", self.autostart_replay, accent) {
|
ui.add_space(3.0);
|
||||||
|
if squared_button_sized(ui, "Turn on replay when this program starts", self.autostart_replay, accent, Some(Vec2::new(btn_w, 26.0))) {
|
||||||
self.autostart_replay = true;
|
self.autostart_replay = true;
|
||||||
self.autostart_on_game = false;
|
self.autostart_on_game = false;
|
||||||
}
|
}
|
||||||
if squared_button(ui, "Turn on replay when starting a game", self.autostart_on_game, accent) {
|
ui.add_space(3.0);
|
||||||
|
if squared_button_sized(ui, "Turn on replay when starting a game", self.autostart_on_game, accent, Some(Vec2::new(btn_w, 26.0))) {
|
||||||
self.autostart_on_game = true;
|
self.autostart_on_game = true;
|
||||||
self.autostart_replay = false;
|
self.autostart_replay = false;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let mut pwr_only = self.autostart_power_only;
|
let mut pwr_only = self.autostart_power_only;
|
||||||
|
|
@ -2417,44 +2523,15 @@ impl ScytheOverlayApp {
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
|
|
||||||
render_section_card(ui, "Audio", accent, |ui| {
|
render_section_card(ui, "Audio", accent, |ui| {
|
||||||
|
ui.label(egui::RichText::new("Audio capture source mode:").size(11.5).color(Color32::from_rgb(180, 185, 190)));
|
||||||
|
ui.add_space(4.0);
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let _ = squared_button(ui, "Add audio track", false, accent);
|
let modes = [("system", "System Audio"), ("mic", "Microphone"), ("both", "Both"), ("muted", "Muted")];
|
||||||
});
|
for (idx, (_, m_label)) in modes.iter().enumerate() {
|
||||||
ui.add_space(8.0);
|
if squared_button(ui, m_label, self.audio_mode_idx == idx, accent) {
|
||||||
|
self.audio_mode_idx = idx;
|
||||||
// Inset Audio Track #1 Box
|
}
|
||||||
egui::Frame::NONE
|
}
|
||||||
.fill(Color32::from_rgb(20, 24, 30))
|
|
||||||
.stroke(Stroke::new(1.0_f32, Color32::from_rgb(34, 40, 50)))
|
|
||||||
.corner_radius(CornerRadius::ZERO)
|
|
||||||
.inner_margin(Margin::same(10_i8))
|
|
||||||
.show(ui, |ui| {
|
|
||||||
ui.label(egui::RichText::new("Audio track #1").size(12.0).strong().color(Color32::WHITE));
|
|
||||||
ui.add_space(6.0);
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
let _ = squared_button(ui, "Add output device", false, accent);
|
|
||||||
let _ = squared_button(ui, "Add input device", false, accent);
|
|
||||||
let _ = squared_button(ui, "Add application audio", false, accent);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.add_space(8.0);
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label(egui::RichText::new("Output device: Default output").size(11.5).color(Color32::WHITE));
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.add_space(8.0);
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
let mut rec_all = true;
|
|
||||||
let _ = toggle_switch(ui, &mut rec_all, accent);
|
|
||||||
ui.label(egui::RichText::new("Record audio from all applications except the selected ones").size(11.0).color(Color32::from_rgb(200, 205, 215)));
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.add_space(6.0);
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label(egui::RichText::new("Track title:").size(11.5).color(Color32::from_rgb(180, 185, 190)));
|
|
||||||
let mut track_t = String::new();
|
|
||||||
ui.add(egui::TextEdit::singleline(&mut track_t).desired_width(180.0));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
|
|
@ -2575,12 +2652,6 @@ impl ScytheOverlayApp {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let _ = squared_button(ui, "Focused monitor", true, accent);
|
let _ = squared_button(ui, "Focused monitor", true, accent);
|
||||||
});
|
});
|
||||||
ui.add_space(6.0);
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
let mut chg_res = false;
|
|
||||||
let _ = toggle_switch(ui, &mut chg_res, accent);
|
|
||||||
ui.label(egui::RichText::new("Change video resolution").size(11.5).color(Color32::WHITE));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
|
|
@ -2661,6 +2732,25 @@ impl ScytheOverlayApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ui.add_space(8.0);
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(egui::RichText::new("Compression quality:").size(11.5).color(Color32::from_rgb(180, 185, 190)));
|
||||||
|
let mut q = self.screenshot_quality;
|
||||||
|
if ui.add(egui::Slider::new(&mut q, 10..=100).suffix("%")).changed() {
|
||||||
|
self.screenshot_quality = q;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.add_space(8.0);
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(egui::RichText::new("Compression preset:").size(11.5).color(Color32::from_rgb(180, 185, 190)));
|
||||||
|
for (p_id, label) in [("fast", "Fast"), ("balanced", "Balanced"), ("max", "Maximum Compression")] {
|
||||||
|
if squared_button(ui, label, self.screenshot_preset == p_id, accent) {
|
||||||
|
self.screenshot_preset = p_id.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
|
|
@ -2791,7 +2881,11 @@ impl ScytheOverlayApp {
|
||||||
(KeybindAction::Menu, "Menu Overlay", &self.config.menu_hotkey),
|
(KeybindAction::Menu, "Menu Overlay", &self.config.menu_hotkey),
|
||||||
(KeybindAction::SaveReplay, "Save Instant Replay", &self.config.save_hotkey),
|
(KeybindAction::SaveReplay, "Save Instant Replay", &self.config.save_hotkey),
|
||||||
(KeybindAction::ToggleRecord, "Start / Stop Record", &self.config.record_hotkey),
|
(KeybindAction::ToggleRecord, "Start / Stop Record", &self.config.record_hotkey),
|
||||||
|
(KeybindAction::PauseRecord, "Pause / Resume Record", &self.config.pause_hotkey),
|
||||||
|
(KeybindAction::Screenshot, "Take Screenshot", &self.config.screenshot_hotkey),
|
||||||
(KeybindAction::ToggleCursor, "Toggle Mouse Cursor", &self.config.cursor_hotkey),
|
(KeybindAction::ToggleCursor, "Toggle Mouse Cursor", &self.config.cursor_hotkey),
|
||||||
|
(KeybindAction::MuteMic, "Mute / Unmute Microphone", &self.config.mute_mic_hotkey),
|
||||||
|
(KeybindAction::MuteSystem, "Mute / Unmute System Audio", &self.config.mute_sys_hotkey),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (action, label, current_hotkey) in binds {
|
for (action, label, current_hotkey) in binds {
|
||||||
|
|
@ -2813,7 +2907,7 @@ impl ScytheOverlayApp {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ui.add_space(6.0);
|
ui.add_space(5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.listening_keybind.is_some() {
|
if self.listening_keybind.is_some() {
|
||||||
|
|
@ -2828,19 +2922,31 @@ impl ScytheOverlayApp {
|
||||||
|
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
if squared_button_sized(ui, "Reset to Defaults", false, accent, Some(Vec2::new(130.0, 26.0))) {
|
if squared_button_sized(ui, "Reset Hotkeys", false, accent, Some(Vec2::new(96.0, 24.0))) {
|
||||||
let old_menu = self.config.menu_hotkey.clone();
|
let old_menu = self.config.menu_hotkey.clone();
|
||||||
let old_save = self.config.save_hotkey.clone();
|
let old_save = self.config.save_hotkey.clone();
|
||||||
let old_rec = self.config.record_hotkey.clone();
|
let old_rec = self.config.record_hotkey.clone();
|
||||||
|
let old_pause = self.config.pause_hotkey.clone();
|
||||||
let old_cur = self.config.cursor_hotkey.clone();
|
let old_cur = self.config.cursor_hotkey.clone();
|
||||||
|
let old_shot = self.config.screenshot_hotkey.clone();
|
||||||
|
let old_mic = self.config.mute_mic_hotkey.clone();
|
||||||
|
let old_sys = self.config.mute_sys_hotkey.clone();
|
||||||
crate::hyprland_binds::unbind_hotkey_async(&old_menu);
|
crate::hyprland_binds::unbind_hotkey_async(&old_menu);
|
||||||
crate::hyprland_binds::unbind_hotkey_async(&old_save);
|
crate::hyprland_binds::unbind_hotkey_async(&old_save);
|
||||||
crate::hyprland_binds::unbind_hotkey_async(&old_rec);
|
crate::hyprland_binds::unbind_hotkey_async(&old_rec);
|
||||||
|
crate::hyprland_binds::unbind_hotkey_async(&old_pause);
|
||||||
crate::hyprland_binds::unbind_hotkey_async(&old_cur);
|
crate::hyprland_binds::unbind_hotkey_async(&old_cur);
|
||||||
|
crate::hyprland_binds::unbind_hotkey_async(&old_shot);
|
||||||
|
crate::hyprland_binds::unbind_hotkey_async(&old_mic);
|
||||||
|
crate::hyprland_binds::unbind_hotkey_async(&old_sys);
|
||||||
self.config.menu_hotkey = "Alt+Z".to_string();
|
self.config.menu_hotkey = "Alt+Z".to_string();
|
||||||
self.config.save_hotkey = "Ctrl+Shift+R".to_string();
|
self.config.save_hotkey = "Ctrl+Shift+R".to_string();
|
||||||
self.config.record_hotkey = "Ctrl+Shift+F9".to_string();
|
self.config.record_hotkey = "Ctrl+Shift+F9".to_string();
|
||||||
|
self.config.pause_hotkey = "Ctrl+Shift+F8".to_string();
|
||||||
|
self.config.screenshot_hotkey = "Ctrl+Shift+S".to_string();
|
||||||
self.config.cursor_hotkey = "Ctrl+Shift+F10".to_string();
|
self.config.cursor_hotkey = "Ctrl+Shift+F10".to_string();
|
||||||
|
self.config.mute_mic_hotkey = "Ctrl+Shift+M".to_string();
|
||||||
|
self.config.mute_sys_hotkey = "Ctrl+Shift+N".to_string();
|
||||||
let _ = self.config.save();
|
let _ = self.config.save();
|
||||||
crate::hyprland_binds::register_hyprland_binds_async(&self.config);
|
crate::hyprland_binds::register_hyprland_binds_async(&self.config);
|
||||||
crate::config::ScytheConfig::notify_daemon_reload();
|
crate::config::ScytheConfig::notify_daemon_reload();
|
||||||
|
|
@ -2851,6 +2957,21 @@ impl ScytheOverlayApp {
|
||||||
|
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
|
|
||||||
|
render_section_card(ui, "Interface Typography", accent, |ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
let mut mono = self.use_monospace_font;
|
||||||
|
if toggle_switch(ui, &mut mono, accent).changed() {
|
||||||
|
self.use_monospace_font = mono;
|
||||||
|
self.config.use_monospace_font = mono;
|
||||||
|
let _ = self.config.save();
|
||||||
|
setup_custom_fonts(ui.ctx(), mono);
|
||||||
|
}
|
||||||
|
ui.label(egui::RichText::new("Use monospace font across interface (Adwaita Mono)").size(11.5).color(Color32::WHITE));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.add_space(10.0);
|
||||||
|
|
||||||
render_section_card(ui, "Startup Integration", accent, |ui| {
|
render_section_card(ui, "Startup Integration", accent, |ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label(egui::RichText::new("Start replay engine on login").size(12.0).color(Color32::WHITE));
|
ui.label(egui::RichText::new("Start replay engine on login").size(12.0).color(Color32::WHITE));
|
||||||
|
|
@ -3684,6 +3805,26 @@ impl eframe::App for ScytheOverlayApp {
|
||||||
self.config.cursor_hotkey = combo.clone();
|
self.config.cursor_hotkey = combo.clone();
|
||||||
("Cursor Toggle", old)
|
("Cursor Toggle", old)
|
||||||
}
|
}
|
||||||
|
KeybindAction::PauseRecord => {
|
||||||
|
let old = self.config.pause_hotkey.clone();
|
||||||
|
self.config.pause_hotkey = combo.clone();
|
||||||
|
("Pause Toggle", old)
|
||||||
|
}
|
||||||
|
KeybindAction::Screenshot => {
|
||||||
|
let old = self.config.screenshot_hotkey.clone();
|
||||||
|
self.config.screenshot_hotkey = combo.clone();
|
||||||
|
("Screenshot", old)
|
||||||
|
}
|
||||||
|
KeybindAction::MuteMic => {
|
||||||
|
let old = self.config.mute_mic_hotkey.clone();
|
||||||
|
self.config.mute_mic_hotkey = combo.clone();
|
||||||
|
("Mute Microphone", old)
|
||||||
|
}
|
||||||
|
KeybindAction::MuteSystem => {
|
||||||
|
let old = self.config.mute_sys_hotkey.clone();
|
||||||
|
self.config.mute_sys_hotkey = combo.clone();
|
||||||
|
("Mute System", old)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
crate::hyprland_binds::unbind_hotkey_async(&old_key);
|
crate::hyprland_binds::unbind_hotkey_async(&old_key);
|
||||||
let _ = self.config.save();
|
let _ = self.config.save();
|
||||||
|
|
@ -3930,7 +4071,8 @@ pub fn run_egui_overlay() {
|
||||||
"scythe-overlay",
|
"scythe-overlay",
|
||||||
options,
|
options,
|
||||||
Box::new(|cc| {
|
Box::new(|cc| {
|
||||||
setup_custom_fonts(&cc.egui_ctx);
|
let cfg = ScytheConfig::load();
|
||||||
|
setup_custom_fonts(&cc.egui_ctx, cfg.use_monospace_font);
|
||||||
Ok(Box::new(ScytheOverlayApp::new()))
|
Ok(Box::new(ScytheOverlayApp::new()))
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
@ -4111,8 +4253,8 @@ pub fn run_egui_toast(title: &str, subtitle: &str, icon: crate::overlay::ToastIc
|
||||||
let _ = eframe::run_native(
|
let _ = eframe::run_native(
|
||||||
"scythe-toast",
|
"scythe-toast",
|
||||||
options,
|
options,
|
||||||
Box::new(|cc| {
|
Box::new(move |cc| {
|
||||||
setup_custom_fonts(&cc.egui_ctx);
|
setup_custom_fonts(&cc.egui_ctx, cfg.use_monospace_font);
|
||||||
Ok(Box::new(app))
|
Ok(Box::new(app))
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue