dash-frontend: toast messages, 📦📎

This commit is contained in:
Aleksander
2025-12-08 22:42:05 +01:00
parent e7746f5981
commit b0985e33af
28 changed files with 316 additions and 80 deletions

1
Cargo.lock generated
View File

@@ -1432,6 +1432,7 @@ dependencies = [
"serde",
"serde_json",
"wgui",
"wlx-common",
]
[[package]]

View File

@@ -22,7 +22,7 @@ resolver = "3"
[workspace.dependencies]
anyhow = "1.0.100"
glam = "0.30.7"
glam = { version = "0.30.7", features = ["mint", "serde"] }
idmap = "0.2.2"
idmap-derive = "0.2.2"
log = "0.4.28"

View File

@@ -6,7 +6,7 @@ edition = "2024"
[dependencies]
anyhow.workspace = true
wgui = { path = "../wgui/" }
glam = { workspace = true }
glam = { workspace = true, features = ["mint", "serde"] }
log = { workspace = true }
rust-embed = { workspace = true }
chrono = "0.4.42"
@@ -14,3 +14,4 @@ gio = "0.21.2"
gtk = "0.18.2"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.145"
wlx-common = { path = "../wlx-common" }

View File

@@ -98,7 +98,6 @@
</div>
<div position="absolute" id="popup_manager" width="100%" height="100%" />
</rectangle>
<!-- BOTTOM PANEL -->
<rectangle

View File

@@ -35,7 +35,13 @@
"SPEAKERS": "Lautsprecher",
"MICROPHONES": "Mikrofone",
"CARDS": "Karten",
"SELECT_AUDIO_CARD_PROFILE": "Wählen Sie das Audio-Kartenprofil"
"SELECT_AUDIO_CARD_PROFILE": "Wählen Sie das Audio-Kartenprofil",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Keine VR-Lautsprecher gefunden. Schalten Sie diese manuell um.",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Kein VR-Mikrofon gefunden. Schalten Sie es manuell um.",
"FAILED_TO_SWITCH_MICROPHONE": "Fehler beim Wechseln des Mikrofons",
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon erfolgreich eingestellt",
"SPEAKERS_SET_SUCCESSFULLY": "Lautsprecher erfolgreich eingestellt",
"DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "Gerät gefunden und initialisiert, aber nicht umgeschaltet"
},
"ACTIONS": {
"RECENTER_PLAYSPACE": "Playspace neu zentrieren"

View File

@@ -35,7 +35,13 @@
"AUTO_SWITCH_TO_VR_AUDIO": "Auto-switch to VR audio",
"SPEAKERS": "Speakers",
"MICROPHONES": "Microphones",
"CARDS": "Cards"
"CARDS": "Cards",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "No VR speakers found. Switch them manually.",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "No VR microphone found. Switch it manually.",
"FAILED_TO_SWITCH_MICROPHONE": "Failed to switch microphone",
"MICROPHONE_SET_SUCCESSFULLY": "Microphone set successfully",
"SPEAKERS_SET_SUCCESSFULLY": "Speakers set successfully",
"DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "Device found and initialized, but not switched"
},
"ACTIONS": {
"RECENTER_PLAYSPACE": "Re-center playspace"

View File

@@ -35,7 +35,13 @@
"SPEAKERS": "Altavoces",
"MICROPHONES": "Micrófonos",
"CARDS": "Tarjetas",
"SELECT_AUDIO_CARD_PROFILE": "Seleccionar perfil de tarjeta de audio"
"SELECT_AUDIO_CARD_PROFILE": "Seleccionar perfil de tarjeta de audio",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "No se encontraron altavoces VR. Actívelos manualmente.",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "No se encontró micrófono VR. Actívelo manualmente.",
"FAILED_TO_SWITCH_MICROPHONE": "No se pudo cambiar el micrófono",
"MICROPHONE_SET_SUCCESSFULLY": "Micrófono configurado correctamente",
"SPEAKERS_SET_SUCCESSFULLY": "Altavoces configurados correctamente",
"DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "Dispositivo encontrado e inicializado, pero no cambiado"
},
"ACTIONS": {
"RECENTER_PLAYSPACE": "Re-centrar espacio de juego"

View File

@@ -35,7 +35,13 @@
"SPEAKERS": "スピーカー",
"MICROPHONES": "マイク",
"CARDS": "カード",
"SELECT_AUDIO_CARD_PROFILE": "オーディオカードプロファイルを選択"
"SELECT_AUDIO_CARD_PROFILE": "オーディオカードプロファイルを選択",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "VRスピーカーが見つかりませんでした。手動で切り替えてください。",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "VRマイクが見つかりませんでした。手動で切り替えてください。",
"FAILED_TO_SWITCH_MICROPHONE": "マイクの切り替えに失敗しました",
"MICROPHONE_SET_SUCCESSFULLY": "マイクの設定が完了しました",
"SPEAKERS_SET_SUCCESSFULLY": "スピーカーを設定しました",
"DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "デバイスが見つかり、初期化されましたが、切り替えられていません"
},
"ACTIONS": {
"RECENTER_PLAYSPACE": "プレイスペースを再中央"

View File

@@ -35,7 +35,13 @@
"SPEAKERS": "Głośniki",
"MICROPHONES": "Mikrofony",
"CARDS": "Karty",
"SELECT_AUDIO_CARD_PROFILE": "Wybierz profil karty dźwiękowej"
"SELECT_AUDIO_CARD_PROFILE": "Wybierz profil karty dźwiękowej",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Brak głośników VR. Włącz je ręcznie.",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Brak mikrofonu VR. Włącz go ręcznie.",
"FAILED_TO_SWITCH_MICROPHONE": "Nie udało się przełączyć mikrofon",
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon ustawiono pomyślnie",
"SPEAKERS_SET_SUCCESSFULLY": "Głośniki ustawiono pomyślnie",
"DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "Urządzenie znalezione i zainicjalizowane, ale nie przełączone"
},
"ACTIONS": {
"RECENTER_PLAYSPACE": "Wycentruj przestrzeń"

View File

@@ -13,6 +13,7 @@ use wgui::{
widget::{label::WidgetLabel, rectangle::WidgetRectangle},
windowing::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement},
};
use wlx_common::timestep::Timestep;
use crate::{
assets, settings,
@@ -21,7 +22,10 @@ use crate::{
settings::TabSettings,
},
task::Tasks,
util::popup_manager::{MountPopupParams, PopupManager, PopupManagerParams},
util::{
popup_manager::{MountPopupParams, PopupManager, PopupManagerParams},
toast_manager::ToastManager,
},
views,
};
@@ -49,6 +53,8 @@ pub struct Frontend {
widgets: FrontendWidgets,
popup_manager: PopupManager,
toast_manager: ToastManager,
timestep: Timestep,
window_audio_settings: WguiWindow,
view_audio_settings: Option<views::audio_settings::View>,
@@ -70,7 +76,7 @@ pub enum FrontendTask {
ShowAudioSettings,
UpdateAudioSettingsView,
RecenterPlayspace,
PushToast(String),
PushToast(Translation),
}
impl Frontend {
@@ -92,7 +98,7 @@ impl Frontend {
},
)?;
let (mut layout, state) = wgui::parser::new_layout_from_assets(
let (layout, state) = wgui::parser::new_layout_from_assets(
&ParseDocumentParams {
globals: globals.clone(),
path: AssetPath::BuiltIn("gui/dashboard.xml"),
@@ -103,10 +109,10 @@ impl Frontend {
let id_popup_manager = state.get_widget_id("popup_manager")?;
let popup_manager = PopupManager::new(PopupManagerParams {
globals: globals.clone(),
layout: &mut layout,
parent_id: id_popup_manager,
})?;
});
let toast_manager = ToastManager::new();
let rc_layout = layout.as_rc();
@@ -116,6 +122,9 @@ impl Frontend {
let id_label_time = state.get_widget_id("label_time")?;
let id_rect_content = state.get_widget_id("rect_content")?;
let mut timestep = Timestep::new();
timestep.set_tps(30.0); // 30 ticks per second
let frontend = Self {
layout: rc_layout.clone(),
state,
@@ -127,8 +136,10 @@ impl Frontend {
id_label_time,
id_rect_content,
},
timestep,
settings: params.settings,
popup_manager,
toast_manager,
window_audio_settings: WguiWindow::default(),
view_audio_settings: None,
};
@@ -165,6 +176,12 @@ impl Frontend {
{
let mut layout = self.layout.borrow_mut();
// always 30 times per second
while self.timestep.on_tick() {
self.toast_manager.tick(&self.globals, &mut layout)?;
}
layout.update(Vec2::new(width, height), timestep_alpha)?;
}
@@ -253,8 +270,8 @@ impl Frontend {
FrontendTask::ShowAudioSettings => self.action_show_audio_settings()?,
FrontendTask::UpdateAudioSettingsView => self.action_update_audio_settings()?,
FrontendTask::RecenterPlayspace => self.action_recenter_playspace()?,
FrontendTask::PushToast(text) => self.push_toast(text)?,
}
FrontendTask::PushToast(content) => self.toast_manager.push(content),
};
Ok(())
}
@@ -269,7 +286,7 @@ impl Frontend {
layout: &mut layout,
parent_id: widget_content.id,
frontend: rc_this,
frontend_widgets: &self.widgets,
//frontend_widgets: &self.widgets,
settings: self.settings.get_mut(),
};
@@ -413,9 +430,4 @@ impl Frontend {
log::info!("todo");
Ok(())
}
fn push_toast(&mut self, text: String) -> anyhow::Result<()> {
log::info!("TODO toast: {}", text);
Ok(())
}
}

View File

@@ -6,7 +6,7 @@ use wgui::{
globals::WguiGlobals,
i18n::Translation,
layout::WidgetPair,
parser::{Fetchable, ParseDocumentParams, ParserData, ParserState},
parser::{Fetchable, ParseDocumentParams, ParserState},
};
use crate::{
@@ -28,6 +28,7 @@ pub struct TabApps {
#[allow(dead_code)]
pub parser_state: ParserState,
#[allow(dead_code)]
state: Rc<RefCell<State>>,
#[allow(dead_code)]
@@ -44,7 +45,7 @@ impl Tab for TabApps {
#[derive(Default)]
struct AppList {
data: Vec<ParserData>,
//data: Vec<ParserData>,
}
// called after the user clicks any desktop entry

View File

@@ -1,12 +1,9 @@
use std::rc::Rc;
use wgui::{
components::button::ComponentButton,
globals::WguiGlobals,
layout::{Layout, WidgetID},
};
use crate::frontend::{FrontendTask, FrontendWidgets, RcFrontend};
use crate::frontend::RcFrontend;
pub mod apps;
pub mod games;
@@ -30,7 +27,6 @@ pub struct TabParams<'a> {
pub layout: &'a mut Layout,
pub parent_id: WidgetID,
pub frontend: &'a RcFrontend,
pub frontend_widgets: &'a FrontendWidgets,
pub settings: &'a mut crate::settings::Settings,
}

View File

@@ -19,3 +19,9 @@ impl<TaskType: Clone + 'static> Tasks<TaskType> {
std::mem::take(&mut *tasks)
}
}
impl<TaskType: Clone + 'static> Default for Tasks<TaskType> {
fn default() -> Self {
Self::new()
}
}

View File

@@ -1,3 +1,4 @@
pub mod desktop_finder;
pub mod pactl_wrapper;
pub mod popup_manager;
pub mod toast_manager;

View File

@@ -17,21 +17,18 @@ use wgui::{
use crate::frontend::{FrontendTask, FrontendTasks};
pub struct PopupManagerParams<'a> {
pub globals: WguiGlobals,
pub layout: &'a mut Layout,
pub struct PopupManagerParams {
pub parent_id: WidgetID,
}
pub struct State {
struct State {
popup_stack: Vec<Weak<RefCell<MountedPopupState>>>,
}
pub struct MountedPopup {
#[allow(dead_code)]
state: ParserState,
id_root: WidgetID, // decorations of a popup
pub id_content: WidgetID, // content of a popup
id_root: WidgetID, // decorations of a popup
layout_tasks: LayoutTasks,
frontend_tasks: FrontendTasks,
}
@@ -52,8 +49,7 @@ impl PopupHandle {
}
pub struct PopupManager {
pub state: Rc<RefCell<State>>,
globals: WguiGlobals,
state: Rc<RefCell<State>>,
parent_id: WidgetID,
}
@@ -104,14 +100,13 @@ impl State {
}
impl PopupManager {
pub fn new(params: PopupManagerParams) -> anyhow::Result<Self> {
Ok(Self {
globals: params.globals,
pub fn new(params: PopupManagerParams) -> Self {
Self {
parent_id: params.parent_id,
state: Rc::new(RefCell::new(State {
popup_stack: Vec::new(),
})),
})
}
}
pub fn refresh(&self, alterables: &mut EventAlterables) {
@@ -147,7 +142,6 @@ impl PopupManager {
let mounted_popup = MountedPopup {
state,
id_content,
id_root,
layout_tasks: layout.tasks.clone(),
frontend_tasks: frontend_tasks.clone(),

View File

@@ -0,0 +1,190 @@
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
use glam::{Mat4, Vec3};
use wgui::{
animation::{Animation, AnimationEasing},
components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR},
drawing::Color,
globals::WguiGlobals,
i18n::Translation,
layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
renderer_vk::{
text::{FontWeight, TextStyle},
util::centered_matrix,
},
taffy::{
self,
prelude::{length, percent},
},
widget::{
div::WidgetDiv,
label::{WidgetLabel, WidgetLabelParams},
rectangle::{WidgetRectangle, WidgetRectangleParams},
util::WLength,
},
};
struct MountedToast {
#[allow(dead_code)]
id_root: WidgetID, // decorations of a toast
layout_tasks: LayoutTasks,
}
struct State {
toast: Option<MountedToast>,
queue: VecDeque<Translation>,
timeout: u32, // in ticks
}
pub struct ToastManager {
state: Rc<RefCell<State>>,
needs_tick: bool,
}
impl Drop for MountedToast {
fn drop(&mut self) {
self.layout_tasks.push(LayoutTask::RemoveWidget(self.id_root));
}
}
const TOAST_DURATION_TICKS: u32 = 90;
impl ToastManager {
pub fn new() -> Self {
Self {
state: Rc::new(RefCell::new(State {
toast: None,
timeout: 0,
queue: VecDeque::new(),
})),
needs_tick: false,
}
}
fn mount_toast(
&self,
globals: &WguiGlobals,
layout: &mut Layout,
state: &mut State,
content: Translation,
) -> anyhow::Result<()> {
let mut globals = globals.get();
let (root, _) = layout.add_topmost_child(
WidgetDiv::create(),
taffy::Style {
position: taffy::Position::Absolute,
size: taffy::Size {
width: percent(1.0),
height: percent(0.8),
},
align_items: Some(taffy::AlignItems::End),
justify_content: Some(taffy::JustifyContent::Center),
..Default::default()
},
)?;
let (rect, _) = layout.add_child(
root.id,
WidgetRectangle::create(WidgetRectangleParams {
color: TOOLTIP_COLOR,
border_color: TOOLTIP_BORDER_COLOR,
border: 2.0,
round: WLength::Percent(1.0),
..Default::default()
}),
taffy::Style {
position: taffy::Position::Relative,
gap: length(4.0),
padding: taffy::Rect {
left: length(16.0),
right: length(16.0),
top: length(8.0),
bottom: length(8.0),
},
..Default::default()
},
)?;
let (label, _) = layout.add_child(
rect.id,
WidgetLabel::create(
&mut globals,
WidgetLabelParams {
content,
style: TextStyle {
weight: Some(FontWeight::Bold),
..Default::default()
},
},
),
taffy::Style { ..Default::default() },
)?;
// show-up animation
layout.animations.add(Animation::new(
rect.id,
160,
AnimationEasing::Linear,
Box::new(move |common, data| {
let pos_showup = AnimationEasing::OutQuint.interpolate((data.pos * 4.0).min(1.0));
let opacity = 1.0 - AnimationEasing::OutQuint.interpolate(((data.pos - 0.75) * 4.0).clamp(0.0, 1.0));
let scale = AnimationEasing::OutBack.interpolate((data.pos * 4.0).min(1.0));
{
let mtx = Mat4::from_translation(Vec3::new(0.0, (1.0 - pos_showup) * 100.0, 0.0))
* Mat4::from_scale(Vec3::new(scale, scale, 1.0));
data.data.transform = centered_matrix(data.widget_boundary.size, &mtx);
}
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
rect.params.color.a = opacity;
rect.params.border_color.a = opacity;
let mut label = common.state.widgets.get_as::<WidgetLabel>(label.id).unwrap();
label.set_color(common, Color::new(1.0, 1.0, 1.0, opacity), true);
common.alterables.mark_redraw();
}),
));
state.toast = Some(MountedToast {
id_root: root.id,
layout_tasks: layout.tasks.clone(),
});
Ok(())
}
pub fn tick(&mut self, globals: &WguiGlobals, layout: &mut Layout) -> anyhow::Result<()> {
if !self.needs_tick {
return Ok(());
}
let mut state = self.state.borrow_mut();
if state.timeout > 0 {
state.timeout -= 1;
}
if state.timeout == 0 {
state.toast = None;
state.timeout = TOAST_DURATION_TICKS;
// mount next
if let Some(content) = state.queue.pop_front() {
self.mount_toast(globals, layout, &mut state, content)?;
}
}
if state.queue.is_empty() && state.toast.is_none() {
self.needs_tick = false;
}
Ok(())
}
pub fn push(&mut self, content: Translation) {
let mut state = self.state.borrow_mut();
state.queue.push_back(content);
self.needs_tick = true;
}
}

View File

@@ -424,14 +424,12 @@ fn switch_sink_card(
}
if sink_found {
frontend_tasks.push(FrontendTask::PushToast(format!(
"Speakers set to \"{}\" successfully!",
name.name
frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key(
format!("[AUDIO.SPEAKERS_SET_SUCCESSFULLY]: {}", name.name).as_str(),
)));
} else {
frontend_tasks.push(FrontendTask::PushToast(format!(
"\"{}\" found and initialized! (not switched)",
name.name
frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key(
format!("[AUDIO.DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED]: {}", name.name).as_str(),
)));
}
@@ -441,18 +439,21 @@ fn switch_sink_card(
fn switch_source(frontend_tasks: &FrontendTasks, source: &pactl_wrapper::Source) -> anyhow::Result<()> {
match pactl_wrapper::set_default_source(source.index) {
Ok(()) => {
frontend_tasks.push(FrontendTask::PushToast(format!(
"Microphone set to \"{}\" successfully!",
if let Some(card_name) = &source.properties.card_name {
card_name
} else {
&source.description
}
frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key(
format!(
"[AUDIO.MICROPHONE_SET_SUCCESSFULLY]: {}",
if let Some(card_name) = &source.properties.card_name {
card_name
} else {
&source.description
}
)
.as_str(),
)));
Ok(())
}
Err(e) => {
frontend_tasks.push(FrontendTask::PushToast(format!("Failed to switch microphone: {:?}", e)));
Translation::from_translation_key(format!("[AUDIO.FAILED_TO_SWITCH_MICROPHONE]: {:?}", e).as_str());
Err(e)
}
}
@@ -471,9 +472,9 @@ fn switch_to_vr_microphone(frontend_tasks: &FrontendTasks) -> anyhow::Result<()>
}
if !switched {
frontend_tasks.push(FrontendTask::PushToast(
"No VR microphone found. Switch it manually.".to_string(),
));
frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key(
"AUDIO.NO_VR_MICROPHONE_SWITCH_MANUALLY",
)));
}
Ok(())
@@ -560,9 +561,9 @@ fn switch_to_vr_speakers(frontend_tasks: &FrontendTasks) -> anyhow::Result<()> {
}
}
frontend_tasks.push(FrontendTask::PushToast(
"No VR speakers found. Switch them manually.".to_string(),
));
frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key(
"AUDIO.NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY",
)));
Ok(())
}

View File

@@ -20,7 +20,7 @@ pub enum AnimationEasing {
}
impl AnimationEasing {
fn interpolate(&self, x: f32) -> f32 {
pub fn interpolate(&self, x: f32) -> f32 {
match self {
Self::Linear => x,
Self::InQuad => x.powi(2),

View File

@@ -95,7 +95,7 @@ pub fn normalize_path(path: &Path) -> PathBuf {
Component::ParentDir => {
match stack.last() {
// ../foo, ../../foo, ./../foo → push ".."
None | Some(Component::ParentDir) | Some(Component::CurDir) => stack.push(Component::ParentDir),
None | Some(Component::ParentDir | Component::CurDir) => stack.push(Component::ParentDir),
// "foo/../bar" → pop "foo" and don't push ".."
Some(Component::Normal(_)) => {
stack.pop();

View File

@@ -1,6 +1,6 @@
use std::{cell::RefCell, rc::Rc};
use taffy::{
AlignItems, JustifyContent,
AlignItems,
prelude::{length, percent},
};

View File

@@ -86,6 +86,9 @@ impl Drop for ComponentTooltip {
}
}
pub const TOOLTIP_COLOR: Color = Color::new(0.1, 0.1, 0.1, 0.9);
pub const TOOLTIP_BORDER_COLOR: Color = Color::new(0.3, 0.3, 0.3, 1.0);
#[allow(clippy::too_many_lines)]
pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Result<(WidgetPair, Rc<ComponentTooltip>)> {
let absolute_boundary = {
@@ -103,7 +106,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
let transform = Mat4::from_translation(Vec3::new(-0.5, 0.0, 0.0));
let (mut pin_left, mut pin_top, pin_align_items, pin_justify_content) = match params.info.side {
let (pin_left, pin_top, pin_align_items, pin_justify_content) = match params.info.side {
TooltipSide::Left => (
absolute_boundary.left() - spacing,
absolute_boundary.top() + absolute_boundary.size.y / 2.0,
@@ -159,8 +162,8 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
let (rect, _) = ess.layout.add_child(
div.id,
WidgetRectangle::create(WidgetRectangleParams {
color: Color::new(0.1, 0.1, 0.1, 0.8),
border_color: Color::new(0.3, 0.3, 0.3, 1.0),
color: TOOLTIP_COLOR,
border_color: TOOLTIP_BORDER_COLOR,
border: 2.0,
round: WLength::Percent(1.0),
..Default::default()

View File

@@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
serde = { version = "1.0.228", features = ["derive"] }
serde = { version = "1.0.228", features = ["derive", "rc"] }
glam = { workspace = true }
chrono = "0.4.42"
idmap = { workspace = true, features = ["serde"] }

View File

@@ -2,4 +2,5 @@ pub mod astr_containers;
pub mod common;
pub mod config;
pub mod overlays;
pub mod timestep;
pub mod windowing;

View File

@@ -52,7 +52,7 @@ rodio = { version = "0.21.1", default-features = false, features = [
"hound",
] }
rosc = { version = "0.11.4", optional = true }
serde = { version = "1.0.225", features = ["derive", "rc"] }
serde = { version = "1.0.228", features = ["derive", "rc"] }
serde_json = "1.0.145"
serde_yaml = "0.9.34"
slotmap = { workspace = true }

View File

@@ -1,4 +1,3 @@
pub mod asset;
pub mod panel;
pub mod timer;
mod timestep;

View File

@@ -1,7 +1,7 @@
use std::{cell::RefCell, rc::Rc};
use button::setup_custom_button;
use glam::{vec2, Affine2, Vec2};
use glam::{Affine2, Vec2, vec2};
use label::setup_custom_label;
use wgui::{
assets::AssetPath,
@@ -15,19 +15,20 @@ use wgui::{
layout::{Layout, LayoutParams, WidgetID},
parser::{CustomAttribsInfoOwned, ParserState},
renderer_vk::context::Context as WguiContext,
widget::{label::WidgetLabel, rectangle::WidgetRectangle, EventResult},
widget::{EventResult, label::WidgetLabel, rectangle::WidgetRectangle},
};
use wlx_common::timestep::Timestep;
use crate::{
backend::input::{Haptics, HoverResult, PointerHit, PointerMode},
state::AppState,
subsystem::hid::WheelDelta,
windowing::backend::{
ui_transform, FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender,
FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender, ui_transform,
},
};
use super::{timer::GuiTimer, timestep::Timestep};
use super::timer::GuiTimer;
pub mod button;
mod helper;

View File

@@ -14,7 +14,7 @@ use wgui::{
parser::Fetchable,
renderer_vk::text::custom_glyph::CustomGlyphData,
taffy,
widget::{sprite::WidgetSprite, EventResult},
widget::{EventResult, sprite::WidgetSprite},
};
use wlx_common::windowing::{OverlayWindowState, Positioning};
@@ -24,16 +24,16 @@ use crate::{
task::{ManagerTask, TaskType},
},
gui::{
panel::{button::BUTTON_EVENTS, GuiPanel, NewGuiPanelParams, OnCustomAttribFunc},
panel::{GuiPanel, NewGuiPanelParams, OnCustomAttribFunc, button::BUTTON_EVENTS},
timer::GuiTimer,
},
overlays::edit::LongPressButtonState,
state::AppState,
windowing::{
OverlaySelector, Z_ORDER_WATCH,
backend::{OverlayEventData, OverlayMeta},
manager::MAX_OVERLAY_SETS,
window::{OverlayWindowConfig, OverlayWindowData},
OverlaySelector, Z_ORDER_WATCH,
},
};
@@ -205,7 +205,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
if idx >= num_children {
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert("idx".into(), idx.to_string().into());
params.insert("src".into(), "".to_string().into());
params.insert("src".into(), String::new().into());
parser_state.instantiate_template(
doc_params, "Device", layout, widget, params,
)?;
@@ -309,7 +309,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
} else {
com.alterables
.set_style(*div, StyleSetRequest::Display(taffy::Display::None));
};
}
}
}
}