Scroll a plugin window's parameters when they don't fit
A plugin window listed every parameter in one grid. VST3 and CLAP plugins expose all of theirs, so a plugin with more parameters than fit on the screen ran off the bottom edge, and the ones below it couldn't be reached (#6). The parameters now scroll inside the window, below the header and the EQ curve, and the window stays on the screen.
This commit is contained in:
parent
7414719f37
commit
16b7c38b6b
|
|
@ -407,44 +407,46 @@ fn plugin_windows(app: &mut SoundApp, ctx: &egui::Context) {
|
|||
if info.id == "eq_7band" || info.id == "eq_1band" {
|
||||
eq_curve(ui, info.id, &ins);
|
||||
}
|
||||
egui::Grid::new(("pg", tid.0, slot)).num_columns(3).show(ui, |ui| {
|
||||
for p in info.params {
|
||||
let v = ins.params.get(p.id).copied().unwrap_or(p.default);
|
||||
ui.label(p.name);
|
||||
let mut x = v;
|
||||
let resp = if !p.choices.is_empty() {
|
||||
let mut idx = x.round().max(0.0) as usize;
|
||||
let r = egui::ComboBox::from_id_salt(("pc", tid.0, slot, p.id))
|
||||
.selected_text(p.choices.get(idx).copied().unwrap_or("?"))
|
||||
.show_ui(ui, |ui| {
|
||||
for (i, c) in p.choices.iter().enumerate() {
|
||||
ui.selectable_value(&mut idx, i, *c);
|
||||
}
|
||||
});
|
||||
x = idx as f32;
|
||||
r.response
|
||||
} else {
|
||||
let mut sl = egui::Slider::new(&mut x, p.min..=p.max).show_value(false);
|
||||
if p.taper == soundcraft_dsp::Taper::Log && p.min > 0.0 {
|
||||
sl = sl.logarithmic(true);
|
||||
}
|
||||
ui.add(sl)
|
||||
};
|
||||
if (x - v).abs() > f32::EPSILON {
|
||||
let _ = app.engine.execute_merged(
|
||||
"mix.insert_param",
|
||||
&json!({"track": tid.0, "slot": slot, "param": p.id, "value": x}),
|
||||
&format!("param:{}:{slot}:{}", tid.0, p.id),
|
||||
);
|
||||
if let Some(pl) = &app.player {
|
||||
// Keep the plugin's own editor in step.
|
||||
pl.editor_set_param(tid, slot, p.id, x);
|
||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||
egui::Grid::new(("pg", tid.0, slot)).num_columns(3).show(ui, |ui| {
|
||||
for p in info.params {
|
||||
let v = ins.params.get(p.id).copied().unwrap_or(p.default);
|
||||
ui.label(p.name);
|
||||
let mut x = v;
|
||||
let resp = if !p.choices.is_empty() {
|
||||
let mut idx = x.round().max(0.0) as usize;
|
||||
let r = egui::ComboBox::from_id_salt(("pc", tid.0, slot, p.id))
|
||||
.selected_text(p.choices.get(idx).copied().unwrap_or("?"))
|
||||
.show_ui(ui, |ui| {
|
||||
for (i, c) in p.choices.iter().enumerate() {
|
||||
ui.selectable_value(&mut idx, i, *c);
|
||||
}
|
||||
});
|
||||
x = idx as f32;
|
||||
r.response
|
||||
} else {
|
||||
let mut sl = egui::Slider::new(&mut x, p.min..=p.max).show_value(false);
|
||||
if p.taper == soundcraft_dsp::Taper::Log && p.min > 0.0 {
|
||||
sl = sl.logarithmic(true);
|
||||
}
|
||||
ui.add(sl)
|
||||
};
|
||||
if (x - v).abs() > f32::EPSILON {
|
||||
let _ = app.engine.execute_merged(
|
||||
"mix.insert_param",
|
||||
&json!({"track": tid.0, "slot": slot, "param": p.id, "value": x}),
|
||||
&format!("param:{}:{slot}:{}", tid.0, p.id),
|
||||
);
|
||||
if let Some(pl) = &app.player {
|
||||
// Keep the plugin's own editor in step.
|
||||
pl.editor_set_param(tid, slot, p.id, x);
|
||||
}
|
||||
}
|
||||
let _ = resp;
|
||||
ui.label(egui::RichText::new(p.format(x)).font(mono(11.0)));
|
||||
ui.end_row();
|
||||
}
|
||||
let _ = resp;
|
||||
ui.label(egui::RichText::new(p.format(x)).font(mono(11.0)));
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
if open {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
use egui_kittest::Harness;
|
||||
use soundcraft_ui_egui::{Services, SoundApp};
|
||||
|
||||
#[test]
|
||||
fn a_long_plugin_window_stays_on_a_short_screen() {
|
||||
let mut app = SoundApp::new(soundcraft_engine::demo::demo_engine(), None, Services::default());
|
||||
let kick = app.engine.session().track_by_name("Kick").unwrap().id;
|
||||
app.ui.plugin_windows = vec![(kick, 0)];
|
||||
let mut h = Harness::builder().with_size(egui::vec2(1200.0, 500.0)).build_ui_state(
|
||||
|ui, app: &mut SoundApp| {
|
||||
app.logic(&ui.ctx().clone());
|
||||
app.ui(ui);
|
||||
},
|
||||
app,
|
||||
);
|
||||
h.run_steps(4);
|
||||
let window = h.ctx.memory(|m| m.area_rect(egui::Id::new(("plugin", kick.0, 0usize)))).unwrap();
|
||||
assert!(window.bottom() <= 500.0, "{window:?}");
|
||||
}
|
||||
Loading…
Reference in New Issue