some sort of ui

This commit is contained in:
2026-04-19 16:20:33 +03:00
parent 4f14980610
commit cdff703f7e
30 changed files with 1504 additions and 184 deletions

136
crates/ui/src/app.rs Normal file
View File

@@ -0,0 +1,136 @@
use params::{ParamId, ParamStore};
use vizia::prelude::*;
#[derive(Clone, Copy, Debug, PartialEq, Data)]
pub enum Panel {
Osc,
Env,
Lfo,
Filter,
Fx,
ModMatrix,
}
impl Panel {
pub const ALL: &'static [Self] = &[
Self::Osc,
Self::Env,
Self::Lfo,
Self::Filter,
Self::Fx,
Self::ModMatrix,
];
pub fn label(self) -> &'static str {
match self {
Self::Osc => "OSC",
Self::Env => "ENV",
Self::Lfo => "LFO",
Self::Filter => "FLT",
Self::Fx => "FX",
Self::ModMatrix => "MOD",
}
}
}
#[derive(Lens, Clone)]
pub struct AppData {
pub params: Vec<f32>,
pub active_panel: Panel,
pub preset_name: String,
pub voice_count: u8,
pub cpu_load: f32,
pub host_bpm: f32,
#[lens(ignore)]
pub store: ParamStore,
}
impl AppData {
pub fn new(store: ParamStore) -> Self {
let params = (0..ParamId::COUNT)
.map(|i| store.get(unsafe { std::mem::transmute::<usize, ParamId>(i) }))
.collect();
Self {
params,
store,
active_panel: Panel::Osc,
preset_name: "Init".into(),
voice_count: 0,
cpu_load: 0.0,
host_bpm: 120.0,
}
}
}
#[derive(Debug)]
pub enum AppEvent {
SetParam(ParamId, f32),
SetPanel(Panel),
UpdateMetrics { voices: u8, cpu: f32 },
}
impl Model for AppData {
fn event(&mut self, _cx: &mut EventContext, event: &mut Event) {
event.map(|e: &AppEvent, _| match e {
AppEvent::SetParam(id, val) => {
let v = val.clamp(0.0, 1.0);
self.params[*id as usize] = v;
self.store.set(*id, v);
}
AppEvent::SetPanel(p) => self.active_panel = *p,
AppEvent::UpdateMetrics { voices, cpu } => {
self.voice_count = *voices;
self.cpu_load = *cpu;
}
});
}
}
pub fn build_root(cx: &mut Context) {
VStack::new(cx, |cx| {
crate::panels::header::build(cx);
HStack::new(cx, |cx| {
VStack::new(cx, |cx| {
for &p in Panel::ALL {
tab_button(cx, p);
}
})
.width(Pixels(56.0))
.height(Stretch(1.0))
.background_color(Color::rgb(14, 14, 26));
Binding::new(cx, AppData::active_panel, |cx, panel_lens| {
VStack::new(cx, |cx| match panel_lens.get(cx) {
Panel::Osc => crate::panels::osc::build(cx),
Panel::Env => crate::panels::env_panel::build(cx),
Panel::Lfo => crate::panels::lfo::build(cx),
Panel::Filter => crate::panels::filter::build(cx),
Panel::Fx => crate::panels::fx::build(cx),
Panel::ModMatrix => crate::panels::mod_matrix::build(cx),
})
.class("panel")
.width(Stretch(1.0))
.height(Stretch(1.0));
});
crate::panels::macro_bar::build(cx);
})
.height(Stretch(1.0));
})
.background_color(Color::rgb(18, 18, 28))
.width(Stretch(1.0))
.height(Stretch(1.0));
}
fn tab_button(cx: &mut Context, p: Panel) {
Binding::new(cx, AppData::active_panel, move |cx, active_lens| {
let al = active_lens.get(cx) == p;
Label::new(cx, p.label())
.class("tab")
.checked(al)
.on_press(move |cx| cx.emit(AppEvent::SetPanel(p)))
.width(Stretch(1.0))
.height(Pixels(44.0))
.text_align(TextAlign::Center);
});
}