mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-01 14:08:38 -06:00
Audio: linked Audio Levels move both channels by the same dB (#2485)
This commit is contained in:
@@ -5494,16 +5494,19 @@ fn vector_editor(app: &mut EffectcraftApp, ui: &mut egui::Ui, ve: &ValueEdit<'_>
|
||||
// Mask Feather: two linked values, never negative (as in After Effects, #203).
|
||||
let feather = prop.match_id == "feather" && layer.props.parent_of(uid).is_some_and(|g| matches!(g.kind, GroupKind::Mask { .. }));
|
||||
let range = if feather { (0.0, 1e9) } else { (-1e9, 1e9) };
|
||||
// Audio Levels link their two channels too, off by default, by the same dB change (#2485).
|
||||
let levels = prop.match_id == "levels" && layer.props.parent_of(uid).is_some_and(|g| g.match_id == "audio");
|
||||
// Scale and Mask Feather: the chain link (Constrain Proportions, on by default).
|
||||
let linkable = feather || (pct && prop.match_id == "scale");
|
||||
let linked = linkable && !app.ui.timeline.unlinked.contains(&uid);
|
||||
let linkable = feather || levels || (pct && prop.match_id == "scale");
|
||||
let linked = linkable && app.ui.timeline.is_linked(uid, !levels);
|
||||
if linkable {
|
||||
let lr = Rect::from_center_size(pos2(x + 7.0, at.y), vec2(14.0, 14.0));
|
||||
let resp = ui.interact(lr, egui::Id::unique(("tl-link", uid)), Sense::click()).on_hover_text(crate::i18n::tr("Constrain Proportions"));
|
||||
let label = if levels { "Link Channels" } else { "Constrain Proportions" };
|
||||
let resp = ui.interact(lr, egui::Id::unique(("tl-link", uid)), Sense::click()).on_hover_text(crate::i18n::tr(label));
|
||||
icons::paint(p, lr, Icon::Link, if linked { t.accent } else { t.text_faint });
|
||||
app.auto.add(&format!("timeline.prop.{uid}.link"), lr, "Constrain Proportions");
|
||||
if resp.clicked() && !app.ui.timeline.unlinked.remove(&uid) {
|
||||
app.ui.timeline.unlinked.insert(uid);
|
||||
app.auto.add(&format!("timeline.prop.{uid}.link"), lr, label);
|
||||
if resp.clicked() {
|
||||
app.ui.timeline.toggle_link(uid, !levels);
|
||||
}
|
||||
x += 18.0;
|
||||
}
|
||||
@@ -5524,7 +5527,8 @@ fn vector_editor(app: &mut EffectcraftApp, ui: &mut egui::Ui, ve: &ValueEdit<'_>
|
||||
// Alt edits one value of a linked pair (Ctrl+Alt is a proportional scrub).
|
||||
let shown = if linked && !ui.input(|i| i.modifiers.alt && !widgets::proportional_scrub(i.modifiers)) { n.min(c.len()) } else { 1 };
|
||||
let from = if shown == 1 { d } else { 0 };
|
||||
for (e, v) in widgets::constrained(c.get(from..from + shown).unwrap_or_default(), d - from, nv).into_iter().enumerate() {
|
||||
let link = if levels { widgets::shifted } else { widgets::constrained };
|
||||
for (e, v) in link(c.get(from..from + shown).unwrap_or_default(), d - from, nv).into_iter().enumerate() {
|
||||
if let Some(slot) = nc.get_mut(from + e) {
|
||||
*slot = v;
|
||||
}
|
||||
|
||||
@@ -820,6 +820,13 @@ pub(crate) fn constrained(c: &[f64], d: usize, v: f64) -> Vec<f64> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Linked values after component `d` of `c` became `v`: the others move by the same amount, so
|
||||
/// linked Audio Levels keep their stereo balance in dB (#2485).
|
||||
pub(crate) fn shifted(c: &[f64], d: usize, v: f64) -> Vec<f64> {
|
||||
let Some(&old) = c.get(d) else { return c.to_vec() };
|
||||
c.iter().enumerate().map(|(e, &x)| if e == d { v } else { x + (v - old) }).collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user