dash and wgui sounds

This commit is contained in:
Aleksander
2026-01-03 15:00:31 +01:00
parent 383bf3b11f
commit feba52c28f
34 changed files with 258 additions and 96 deletions

1
Cargo.lock generated
View File

@@ -6801,6 +6801,7 @@ dependencies = [
"serde",
"smol",
"wayvr-ipc",
"wgui",
"xdg 3.0.0",
]

Binary file not shown.

Binary file not shown.

View File

@@ -8,19 +8,20 @@ use wgui::{
font_config::WguiFontConfig,
globals::WguiGlobals,
i18n::Translation,
layout::{Layout, LayoutParams, WidgetID},
layout::{Layout, LayoutParams, LayoutUpdateParams, LayoutUpdateResult, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState},
sound::WguiSoundType,
task::Tasks,
widget::{label::WidgetLabel, rectangle::WidgetRectangle},
windowing::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement},
};
use wlx_common::{dash_interface::BoxDashInterface, timestep::Timestep};
use wlx_common::{audio, dash_interface::BoxDashInterface, timestep::Timestep};
use crate::{
assets, settings,
tab::{
apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses, settings::TabSettings,
Tab, TabType,
Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses,
settings::TabSettings,
},
util::{
desktop_finder::DesktopFinder,
@@ -68,6 +69,13 @@ pub struct Frontend<T> {
pub(crate) desktop_finder: DesktopFinder,
}
pub struct FrontendUpdateParams<'a, T> {
pub data: &'a mut T,
pub width: f32,
pub height: f32,
pub timestep_alpha: f32,
}
pub struct InitParams<T> {
pub settings: Box<dyn settings::SettingsIO>,
pub interface: BoxDashInterface<T>,
@@ -164,15 +172,27 @@ impl<T: 'static> Frontend<T> {
Ok(frontend)
}
pub fn update(&mut self, data: &mut T, width: f32, height: f32, timestep_alpha: f32) -> anyhow::Result<()> {
pub fn play_startup_sound(
&mut self,
audio_system: &mut audio::AudioSystem,
audio_sample_player: &mut audio::SamplePlayer,
) -> anyhow::Result<()> {
// play startup sound
let mut assets = self.globals.assets_builtin();
audio_sample_player.register_mp3_sample_from_assets("dash_startup", assets.as_mut(), "sound/startup.mp3")?;
audio_sample_player.play_sample(audio_system, "dash_startup");
Ok(())
}
pub fn update(&mut self, params: FrontendUpdateParams<T>) -> anyhow::Result<LayoutUpdateResult> {
let mut tasks = self.tasks.drain();
while let Some(task) = tasks.pop_front() {
self.process_task(data, task)?;
self.process_task(params.data, task)?;
}
if let Some(mut tab) = self.current_tab.take() {
tab.update(self, data)?;
tab.update(self, params.data)?;
self.current_tab = Some(tab);
}
@@ -180,13 +200,14 @@ impl<T: 'static> Frontend<T> {
// process async runtime tasks
while self.executor.try_tick() {}
self.tick(width, height, timestep_alpha)?;
let res = self.tick(params)?;
self.ticks += 1;
Ok(())
Ok(res)
}
fn tick(&mut self, width: f32, height: f32, timestep_alpha: f32) -> anyhow::Result<()> {
fn tick(&mut self, params: FrontendUpdateParams<T>) -> anyhow::Result<LayoutUpdateResult> {
// fixme: timer events instead of this thing
if self.ticks.is_multiple_of(1000) {
self.update_time()?;
@@ -197,11 +218,12 @@ impl<T: 'static> Frontend<T> {
while self.timestep.on_tick() {
self.toast_manager.tick(&self.globals, &mut self.layout)?;
}
self.layout.update(Vec2::new(width, height), timestep_alpha)?;
}
Ok(())
self.layout.update(&mut LayoutUpdateParams {
size: Vec2::new(params.width, params.height),
timestep_alpha: params.timestep_alpha,
})
}
fn update_time(&mut self) -> anyhow::Result<()> {

View File

@@ -68,7 +68,7 @@ pub struct CardProperties {
pub device_name: String, // alsa_card.pci-0000_0c_00.4
#[serde(rename = "device.nick")]
pub device_nick: String, // HD-Audio Generic
pub device_nick: Option<String>, // HD-Audio Generic
}
#[derive(Clone, Serialize, Deserialize, Debug)]
@@ -296,7 +296,12 @@ pub fn list_cards() -> anyhow::Result<Vec<Card>> {
let mut cards: Vec<Card> = serde_json::from_str(json_str)?;
// exclude card which has "Loopback" in name
cards.retain(|card| card.properties.device_nick != "Loopback");
cards.retain(|card| {
if let Some(nick) = &card.properties.device_nick {
return nick != "Loopback";
};
true
});
Ok(cards)
}

View File

@@ -0,0 +1 @@
../../../wlx-overlay-s/src/assets/sound/wgui_button_press.mp3

View File

@@ -0,0 +1 @@
../../../wlx-overlay-s/src/assets/sound/wgui_button_release.mp3

View File

@@ -0,0 +1 @@
../../../wlx-overlay-s/src/assets/sound/wgui_mouse_enter.mp3

View File

@@ -18,6 +18,7 @@ use vulkano::{
sync::GpuFuture,
};
use wgui::{
assets::AssetProvider,
event::{MouseButtonIndex, MouseDownEvent, MouseMotionEvent, MouseUpEvent, MouseWheelEvent},
gfx::{WGfx, cmd::WGfxClearMode},
renderer_vk::{self},
@@ -27,7 +28,7 @@ use winit::{
event_loop::ControlFlow,
keyboard::{KeyCode, PhysicalKey},
};
use wlx_common::timestep::Timestep;
use wlx_common::{audio, timestep::Timestep};
use crate::{
rate_limiter::RateLimiter,
@@ -59,12 +60,15 @@ fn init_logging() {
.init();
}
fn load_testbed() -> anyhow::Result<Box<dyn Testbed>> {
fn load_testbed(audio_sample_player: &mut audio::SamplePlayer) -> anyhow::Result<Box<dyn Testbed>> {
let mut assets = Box::new(assets::Asset {});
audio_sample_player.register_wgui_samples(assets.as_mut())?;
let name = std::env::var("TESTBED").unwrap_or_default();
Ok(match name.as_str() {
"dashboard" => Box::new(TestbedDashboard::new()?),
"" => Box::new(TestbedGeneric::new()?),
_ => Box::new(TestbedAny::new(&name)?),
"" => Box::new(TestbedGeneric::new(assets)?),
_ => Box::new(TestbedAny::new(assets, &name)?),
})
}
@@ -98,7 +102,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut scale = window.scale_factor() as f32;
let mut testbed = load_testbed()?;
let mut audio_system = audio::AudioSystem::new();
let mut audio_sample_player = audio::SamplePlayer::new();
let mut testbed = load_testbed(&mut audio_sample_player)?;
let mut mouse = Vec2::ZERO;
@@ -291,6 +297,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
width: (swapchain_size[0] as f32 / scale) as _,
height: (swapchain_size[1] as f32 / scale) as _,
timestep_alpha: timestep.alpha,
audio_system: &mut audio_system,
audio_sample_player: &mut audio_sample_player,
})
.unwrap();

View File

@@ -1,13 +1,24 @@
use wgui::layout::Layout;
use wgui::layout::{Layout, LayoutUpdateResult};
use wlx_common::audio;
pub mod testbed_any;
pub mod testbed_dashboard;
pub mod testbed_generic;
pub struct TestbedUpdateParams {
pub struct TestbedUpdateParams<'a> {
pub width: f32,
pub height: f32,
pub timestep_alpha: f32,
pub audio_system: &'a mut audio::AudioSystem,
pub audio_sample_player: &'a mut audio::SamplePlayer,
}
impl<'a> TestbedUpdateParams<'a> {
pub fn process_layout_result(&mut self, res: LayoutUpdateResult) {
self
.audio_sample_player
.play_wgui_samples(self.audio_system, res.sounds_to_play);
}
}
pub trait Testbed {

View File

@@ -9,7 +9,7 @@ use wgui::{
assets::AssetPath,
font_config::WguiFontConfig,
globals::WguiGlobals,
layout::{Layout, LayoutParams},
layout::{Layout, LayoutParams, LayoutUpdateParams},
parser::{ParseDocumentParams, ParserState},
};
@@ -21,7 +21,7 @@ pub struct TestbedAny {
}
impl TestbedAny {
pub fn new(name: &str) -> anyhow::Result<Self> {
pub fn new(assets: Box<assets::Asset>, name: &str) -> anyhow::Result<Self> {
let path = if name.ends_with(".xml") {
AssetPath::FileOrBuiltIn(name)
} else {
@@ -29,7 +29,7 @@ impl TestbedAny {
};
let globals = WguiGlobals::new(
Box::new(assets::Asset {}),
assets,
wgui::globals::Defaults::default(),
&WguiFontConfig::default(),
PathBuf::new(), // cwd
@@ -48,11 +48,12 @@ impl TestbedAny {
}
impl Testbed for TestbedAny {
fn update(&mut self, params: TestbedUpdateParams) -> anyhow::Result<()> {
self.layout.update(
Vec2::new(params.width, params.height),
params.timestep_alpha,
)?;
fn update(&mut self, mut params: TestbedUpdateParams) -> anyhow::Result<()> {
let res = self.layout.update(&mut LayoutUpdateParams {
size: Vec2::new(params.width, params.height),
timestep_alpha: params.timestep_alpha,
})?;
params.process_layout_result(res);
Ok(())
}

View File

@@ -1,6 +1,6 @@
use crate::testbed::{Testbed, TestbedUpdateParams};
use dash_frontend::{
frontend,
frontend::{self, FrontendUpdateParams},
settings::{self, SettingsIO},
};
use wgui::layout::Layout;
@@ -70,13 +70,15 @@ impl TestbedDashboard {
}
impl Testbed for TestbedDashboard {
fn update(&mut self, params: TestbedUpdateParams) -> anyhow::Result<()> {
self.frontend.update(
&mut (), /* nothing */
params.width,
params.height,
params.timestep_alpha,
)
fn update(&mut self, mut params: TestbedUpdateParams) -> anyhow::Result<()> {
let res = self.frontend.update(FrontendUpdateParams {
data: &mut (), /* nothing */
width: params.width,
height: params.height,
timestep_alpha: params.timestep_alpha,
})?;
params.process_layout_result(res);
Ok(())
}
fn layout(&mut self) -> &mut Layout {

View File

@@ -17,7 +17,7 @@ use wgui::{
font_config::WguiFontConfig,
globals::WguiGlobals,
i18n::Translation,
layout::{Layout, LayoutParams, Widget},
layout::{Layout, LayoutParams, LayoutUpdateParams, Widget},
parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState},
taffy,
task::Tasks,
@@ -73,11 +73,11 @@ fn handle_button_click(button: Rc<ComponentButton>, label: Widget, text: &'stati
}
impl TestbedGeneric {
pub fn new() -> anyhow::Result<Self> {
pub fn new(assets: Box<assets::Asset>) -> anyhow::Result<Self> {
const XML_PATH: AssetPath = AssetPath::BuiltIn("gui/various_widgets.xml");
let globals = WguiGlobals::new(
Box::new(assets::Asset {}),
assets,
wgui::globals::Defaults::default(),
&WguiFontConfig::default(),
PathBuf::new(), // cwd
@@ -223,10 +223,12 @@ impl Testbed for TestbedGeneric {
let data = self.data.clone();
let mut data = data.borrow_mut();
self.layout.update(
Vec2::new(params.width, params.height),
params.timestep_alpha,
)?;
let res = self.layout.update(&mut LayoutUpdateParams {
size: Vec2::new(params.width, params.height),
timestep_alpha: params.timestep_alpha,
})?;
params.process_layout_result(res);
for task in self.tasks.drain() {
self.process_task(&task, &mut params, &mut data)?;

View File

@@ -10,6 +10,7 @@ use crate::{
text::{FontWeight, TextStyle, custom_glyph::CustomGlyphData},
util::centered_matrix,
},
sound::WguiSoundType,
widget::{
self, ConstructEssentials, EventResult, WidgetData,
label::{WidgetLabel, WidgetLabelParams},
@@ -270,6 +271,7 @@ fn register_event_mouse_enter(
listeners.register(
EventListenerKind::MouseEnter,
Box::new(move |common, event_data, (), ()| {
common.alterables.play_sound(WguiSoundType::ButtonMouseEnter);
common.alterables.trigger_haptics();
common.alterables.mark_redraw();
common
@@ -332,6 +334,7 @@ fn register_event_mouse_press(state: Rc<RefCell<State>>, listeners: &mut EventLi
);
common.alterables.trigger_haptics();
common.alterables.play_sound(WguiSoundType::ButtonPress);
common.alterables.mark_redraw();
if state.hovered {
@@ -362,6 +365,7 @@ fn register_event_mouse_release(
}
common.alterables.trigger_haptics();
common.alterables.play_sound(WguiSoundType::ButtonRelease);
common.alterables.mark_redraw();
if state.down {

View File

@@ -11,6 +11,7 @@ use crate::{
animation::{self, Animation},
i18n::I18n,
layout::{LayoutState, LayoutTask, WidgetID},
sound::WguiSoundType,
stack::{ScissorStack, Transform, TransformStack},
widget::{EventResult, WidgetData, WidgetObj},
};
@@ -140,6 +141,10 @@ impl EventAlterables {
pub fn animate(&mut self, animation: Animation) {
self.animations.push(animation);
}
pub fn play_sound(&mut self, sound_type: WguiSoundType) {
self.tasks.push(LayoutTask::PlaySound(sound_type));
}
}
pub struct CallbackDataCommon<'a> {

View File

@@ -1,6 +1,6 @@
use std::{
cell::{RefCell, RefMut},
collections::{HashMap, HashSet, VecDeque},
collections::{HashMap, HashSet},
io::Write,
rc::{Rc, Weak},
};
@@ -11,6 +11,8 @@ use crate::{
drawing::{self, ANSI_BOLD_CODE, ANSI_RESET_CODE, Boundary, push_scissor_stack, push_transform_stack},
event::{self, CallbackDataCommon, EventAlterables},
globals::WguiGlobals,
sound::WguiSoundType,
task::Tasks,
widget::{self, EventParams, EventResult, WidgetObj, WidgetState, WidgetStateFlags, div::WidgetDiv},
};
@@ -119,25 +121,24 @@ pub struct ModifyLayoutStateData<'a> {
pub layout: &'a mut Layout,
}
pub struct LayoutUpdateParams {
pub size: Vec2, // logical resolution
pub timestep_alpha: f32,
}
pub struct LayoutUpdateResult {
pub sounds_to_play: Vec<WguiSoundType>,
}
pub type ModifyLayoutStateFunc = Box<dyn Fn(ModifyLayoutStateData) -> anyhow::Result<()>>;
pub enum LayoutTask {
RemoveWidget(WidgetID),
ModifyLayoutState(ModifyLayoutStateFunc),
PlaySound(WguiSoundType),
}
#[derive(Clone)]
pub struct LayoutTasks(pub Rc<RefCell<VecDeque<LayoutTask>>>);
impl LayoutTasks {
fn new() -> Self {
Self(Rc::new(RefCell::new(VecDeque::new())))
}
pub fn push(&self, task: LayoutTask) {
self.0.borrow_mut().push_back(task);
}
}
pub type LayoutTasks = Tasks<LayoutTask>;
pub struct Layout {
pub state: LayoutState,
@@ -146,6 +147,7 @@ pub struct Layout {
components_to_refresh_once: HashSet<Component>,
registered_components_to_refresh: HashMap<taffy::NodeId, Component>,
sounds_to_play_once: Vec<WguiSoundType>,
pub widgets_to_tick: Vec<WidgetID>,
@@ -266,15 +268,12 @@ impl Layout {
}
pub fn get_parent(&self, widget_id: WidgetID) -> Option<(WidgetID, taffy::NodeId)> {
let Some(node_id) = self.state.nodes.get(widget_id) else {
return None;
};
let node_id = self.state.nodes.get(widget_id)?;
self.state.tree.parent(*node_id).map(|parent_id| {
let parent_widget_id = self.state.tree.get_node_context(parent_id).unwrap();
(*parent_widget_id, parent_id)
}
)
let parent_widget_id = self.state.tree.get_node_context(parent_id).unwrap();
(*parent_widget_id, parent_id)
})
}
fn collect_children_ids_recursive(&self, widget_id: WidgetID, out: &mut Vec<(WidgetID, taffy::NodeId)>) {
@@ -575,6 +574,7 @@ impl Layout {
registered_components_to_refresh: HashMap::new(),
widgets_to_tick: Vec::new(),
tasks: LayoutTasks::new(),
sounds_to_play_once: Vec::new(),
})
}
@@ -659,12 +659,17 @@ impl Layout {
Ok(())
}
pub fn update(&mut self, size: Vec2, timestep_alpha: f32) -> anyhow::Result<()> {
pub fn update(&mut self, params: &mut LayoutUpdateParams) -> anyhow::Result<LayoutUpdateResult> {
let mut alterables = EventAlterables::default();
self.animations.process(&self.state, &mut alterables, timestep_alpha);
self
.animations
.process(&self.state, &mut alterables, params.timestep_alpha);
self.process_alterables(alterables)?;
self.try_recompute_layout(size)?;
Ok(())
self.try_recompute_layout(params.size)?;
Ok(LayoutUpdateResult {
sounds_to_play: std::mem::take(&mut self.sounds_to_play_once),
})
}
pub fn tick(&mut self) -> anyhow::Result<()> {
@@ -677,8 +682,7 @@ impl Layout {
}
pub fn process_tasks(&mut self) -> anyhow::Result<()> {
let tasks = self.tasks.clone();
let mut tasks = tasks.0.borrow_mut();
let mut tasks = self.tasks.drain();
while let Some(task) = tasks.pop_front() {
match task {
LayoutTask::RemoveWidget(widget_id) => {
@@ -687,6 +691,11 @@ impl Layout {
LayoutTask::ModifyLayoutState(callback) => {
(*callback)(ModifyLayoutStateData { layout: self })?;
}
LayoutTask::PlaySound(sound) => {
if !self.sounds_to_play_once.contains(&sound) {
self.sounds_to_play_once.push(sound);
}
}
}
}

View File

@@ -34,6 +34,7 @@ pub mod i18n;
pub mod layout;
pub mod parser;
pub mod renderer_vk;
pub mod sound;
pub mod stack;
pub mod task;
pub mod widget;

6
wgui/src/sound.rs Normal file
View File

@@ -0,0 +1,6 @@
#[derive(Clone, Eq, PartialEq)]
pub enum WguiSoundType {
ButtonMouseEnter,
ButtonPress,
ButtonRelease,
}

View File

@@ -16,6 +16,7 @@ serde = { workspace = true, features = ["rc"] }
xdg.workspace = true
chrono = "0.4.42"
smol = "2.0.2"
wgui = { path = "../wgui/" }
rodio = { version = "0.21.1", default-features = false, features = [
"playback",
"mp3",

View File

@@ -1,6 +1,10 @@
use std::{collections::HashMap, io::Cursor};
use rodio::Source;
use wgui::{
assets::{self, AssetProvider},
sound::WguiSoundType,
};
pub struct AudioSystem {
audio_stream: Option<rodio::OutputStream>,
@@ -15,6 +19,14 @@ pub struct SamplePlayer {
samples: HashMap<String, AudioSample>,
}
fn get_sample_name_from_wgui_sound_type(sound: WguiSoundType) -> &'static str {
match sound {
WguiSoundType::ButtonMouseEnter => "wgui_mouse_enter",
WguiSoundType::ButtonPress => "wgui_button_press",
WguiSoundType::ButtonRelease => "wgui_button_release",
}
}
impl SamplePlayer {
pub fn new() -> Self {
Self {
@@ -23,9 +35,39 @@ impl SamplePlayer {
}
pub fn register_sample(&mut self, sample_name: &str, sample: AudioSample) {
log::debug!("registering audio sample \"{sample_name}\"");
self.samples.insert(String::from(sample_name), sample);
}
pub fn register_mp3_sample_from_assets(
&mut self,
sample_name: &str,
assets: &mut dyn AssetProvider,
path: &str,
) -> anyhow::Result<()> {
// load only once
if self.samples.contains_key(sample_name) {
return Ok(());
}
let data = assets.load_from_path(path)?;
self.register_sample(sample_name, AudioSample::from_mp3(&data)?);
Ok(())
}
pub fn register_wgui_samples(&mut self, assets: &mut dyn AssetProvider) -> anyhow::Result<()> {
let mut load = |sound: WguiSoundType| -> anyhow::Result<()> {
let sample_name = get_sample_name_from_wgui_sound_type(sound);
self.register_mp3_sample_from_assets(sample_name, assets, &format!("sound/{}.mp3", sample_name))
};
load(WguiSoundType::ButtonPress)?;
load(WguiSoundType::ButtonRelease)?;
load(WguiSoundType::ButtonMouseEnter)?;
Ok(())
}
pub fn play_sample(&mut self, system: &mut AudioSystem, sample_name: &str) {
let Some(sample) = self.samples.get(sample_name) else {
log::error!("failed to play sample by name {}", sample_name);
@@ -34,6 +76,12 @@ impl SamplePlayer {
system.play_sample(sample);
}
pub fn play_wgui_samples(&mut self, system: &mut AudioSystem, samples: Vec<WguiSoundType>) {
for sample in samples {
self.play_sample(system, get_sample_name_from_wgui_sound_type(sample));
}
}
}
impl Default for SamplePlayer {

View File

@@ -0,0 +1,8 @@
use wgui::layout::LayoutUpdateResult;
use crate::state::AppState;
pub fn process_layout_result(app: &mut AppState, res: LayoutUpdateResult) {
app.audio_sample_player
.play_wgui_samples(&mut app.audio_system, res.sounds_to_play);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -13,7 +13,7 @@ use wgui::{
MouseMotionEvent, MouseUpEvent, MouseWheelEvent,
},
gfx::cmd::WGfxClearMode,
layout::{Layout, LayoutParams, WidgetID},
layout::{Layout, LayoutParams, LayoutUpdateParams, WidgetID},
parser::{CustomAttribsInfoOwned, Fetchable, ParserState},
renderer_vk::context::Context as WguiContext,
widget::{EventResult, label::WidgetLabel},
@@ -22,6 +22,7 @@ use wlx_common::overlays::{BackendAttrib, BackendAttribValue};
use wlx_common::timestep::Timestep;
use crate::{
app_misc,
backend::input::{Haptics, HoverResult, PointerHit, PointerMode},
state::AppState,
subsystem::hid::WheelDelta,
@@ -211,8 +212,15 @@ impl<S: 'static> GuiPanel<S> {
})
}
pub fn update_layout(&mut self) -> anyhow::Result<()> {
self.layout.update(self.max_size, 0.0)
pub fn update_layout(&mut self, app: &mut AppState) -> anyhow::Result<()> {
app_misc::process_layout_result(
app,
self.layout.update(&mut LayoutUpdateParams {
size: self.max_size / self.gui_scale,
timestep_alpha: self.timestep.alpha,
})?,
);
Ok(())
}
pub fn push_event(&mut self, app: &mut AppState, event: &WguiEvent) -> EventResult {
@@ -236,9 +244,9 @@ impl<S: 'static> GuiPanel<S> {
}
impl<S: 'static> OverlayBackend for GuiPanel<S> {
fn init(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
fn init(&mut self, app: &mut AppState) -> anyhow::Result<()> {
if self.layout.content_size.x * self.layout.content_size.y != 0.0 {
self.update_layout()?;
self.update_layout(app)?;
self.interaction_transform = Some(ui_transform([
self.layout.content_size.x as _,
self.layout.content_size.y as _,
@@ -297,9 +305,7 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
self.context
.update_viewport(&mut app.wgui_shared, rdr.extent, self.gui_scale)?;
self.layout
.update(self.max_size / self.gui_scale, self.timestep.alpha)?;
self.update_layout(app)?;
let globals = self.layout.state.globals.clone(); // sorry
let mut globals = globals.get();

View File

@@ -17,6 +17,7 @@
clippy::cargo_common_metadata,
clippy::option_if_let_else
)]
mod app_misc;
mod backend;
mod config;
mod config_io;

View File

@@ -16,7 +16,7 @@ pub static ANCHOR_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("anchor"
pub fn create_anchor(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
let mut panel = GuiPanel::new_from_template(app, "gui/anchor.xml", (), Default::default())?;
panel.update_layout()?;
panel.update_layout(app)?;
Ok(OverlayWindowConfig {
name: ANCHOR_NAME.clone(),
@@ -41,7 +41,7 @@ pub static GRAB_HELP_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("grab
pub fn create_grab_help(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
let mut panel = GuiPanel::new_from_template(app, "gui/grab-help.xml", (), Default::default())?;
panel.update_layout()?;
panel.update_layout(app)?;
let id_watch = panel.parser_state.data.get_widget_id("grabbing_watch")?;
let id_static = panel.parser_state.data.get_widget_id("grabbing_static")?;

View File

@@ -42,7 +42,7 @@ pub fn create_custom(app: &mut AppState, name: Arc<str>) -> Option<OverlayWindow
.ok()?;
panel
.update_layout()
.update_layout(app)
.inspect_err(|e| log::warn!("Error layouting '{name}': {e:?}"))
.ok()?;

View File

@@ -1,5 +1,5 @@
use dash_frontend::{
frontend,
frontend::{self, FrontendUpdateParams},
settings::{self, SettingsIO},
};
use glam::{Affine2, Affine3A, Vec2, vec2, vec3};
@@ -27,6 +27,7 @@ use wlx_common::{
};
use crate::{
app_misc,
backend::{
input::{Haptics, HoverResult, PointerHit, PointerMode},
task::{OverlayTask, PlayspaceTask, TaskType},
@@ -103,10 +104,13 @@ impl DashFrontend {
let settings = SimpleSettingsIO::new();
let interface = DashInterfaceLive::new();
let frontend = frontend::Frontend::new(frontend::InitParams {
let mut frontend = frontend::Frontend::new(frontend::InitParams {
settings: Box::new(settings),
interface: Box::new(interface),
})?;
frontend.play_startup_sound(&mut app.audio_system, &mut app.audio_sample_player)?;
let context = WguiContext::new(&mut app.wgui_shared, 1.0)?;
Ok(Self {
inner: frontend,
@@ -119,12 +123,14 @@ impl DashFrontend {
}
fn update(&mut self, app: &mut AppState, timestep_alpha: f32) -> anyhow::Result<()> {
self.inner.update(
app,
DASH_RES_VEC2.x / GUI_SCALE,
DASH_RES_VEC2.y / GUI_SCALE,
let res = self.inner.update(FrontendUpdateParams {
data: app,
width: DASH_RES_VEC2.x / GUI_SCALE,
height: DASH_RES_VEC2.y / GUI_SCALE,
timestep_alpha,
)
})?;
app_misc::process_layout_result(app, res);
Ok(())
}
fn push_event(&mut self, event: &WguiEvent) -> EventResult {

View File

@@ -167,7 +167,7 @@ impl OverlayBackend for EditModeBackendWrapper {
let gui_scale = (new_size.x / 750.0).min(new_size.y / 300.0);
self.panel.gui_scale = (gui_scale * 4.0).round() / 4.0;
self.panel.update_layout()?;
self.panel.update_layout(app)?;
}
self.can_render_inner = true;

View File

@@ -1,13 +1,13 @@
use std::{collections::HashMap, rc::Rc};
use crate::{gui::panel::GuiPanel, state::AppState, subsystem::hid::XkbKeymap};
use crate::{app_misc, gui::panel::GuiPanel, state::AppState, subsystem::hid::XkbKeymap};
use glam::{FloatExt, Mat4, Vec2, vec2, vec3};
use wgui::{
animation::{Animation, AnimationEasing},
assets::AssetPath,
drawing::{self, Color},
event::{self, CallbackMetadata, EventListenerKind},
layout::LayoutParams,
layout::{LayoutParams, LayoutUpdateParams},
parser::Fetchable,
renderer_vk::util,
taffy::{self, prelude::length},
@@ -264,7 +264,13 @@ pub(super) fn create_keyboard_panel(
}
}
panel.layout.update(vec2(2048., 2048.), 0.0)?;
app_misc::process_layout_result(
app,
panel.layout.update(&mut LayoutUpdateParams {
size: vec2(2048., 2048.),
timestep_alpha: 0.0,
})?,
);
panel.parser_state = gui_state_key;
Ok(panel)

View File

@@ -179,7 +179,10 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<OverlayWindowConfig> {
.inspect_err(|e| log::error!("Could not create toast: {e:?}"))
.ok()?;
panel.update_layout().context("layout update failed").ok()?;
panel
.update_layout(app)
.context("layout update failed")
.ok()?;
Some(OverlayWindowConfig {
name: TOAST_NAME.clone(),

View File

@@ -551,7 +551,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
align_to_hmd: false,
};
panel.update_layout()?;
panel.update_layout(app)?;
Ok(OverlayWindowConfig {
name: WATCH_NAME.into(),

View File

@@ -109,6 +109,9 @@ impl AppState {
audio::AudioSample::from_mp3(include_bytes!("res/toast.mp3"))?,
);
let mut assets = Box::new(gui::asset::GuiAsset {});
audio_sample_player.register_wgui_samples(assets.as_mut())?;
let mut defaults = wgui::globals::Defaults::default();
{
@@ -147,7 +150,7 @@ impl AppState {
anchor: Affine3A::IDENTITY,
anchor_grabbed: false,
wgui_globals: WguiGlobals::new(
Box::new(gui::asset::GuiAsset {}),
assets,
defaults,
&WguiFontConfig::default(),
get_config_file_path(&theme),