From e0f25c77bb56d763d3b5f1312f76d0120f06769b Mon Sep 17 00:00:00 2001 From: caldiag Date: Wed, 14 Oct 2026 18:27:25 -0300 Subject: [PATCH 1/2] when double-clicking an effect property, it reveals that effect in the timeline --- crates/ui-egui/src/panels/effect_controls.rs | 5 ++- crates/ui-egui/src/panels/timeline.rs | 41 ++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/crates/ui-egui/src/panels/effect_controls.rs b/crates/ui-egui/src/panels/effect_controls.rs index bad1db39..73798880 100644 --- a/crates/ui-egui/src/panels/effect_controls.rs +++ b/crates/ui-egui/src/panels/effect_controls.rs @@ -272,7 +272,10 @@ fn prop_row( let name_clip = Rect::from_min_max(pos2(swr.max.x + 6.0, r.min.y), pos2(vx - 6.0, r.max.y)); app.auto.add(&format!("effectControls.prop.{uid}.name"), name_clip, &prop.name); p.with_clip_rect(name_clip.intersect(p.clip_rect())).text(pos2(swr.max.x + 6.0, cy), Align2::LEFT_CENTER, &prop.name, Tokens::ui(12.0), t.text); - ui.interact(name_clip, egui::Id::new(("ec-prop-name", uid)), Sense::click()); + let name_response = ui.interact(name_clip, egui::Id::new(("ec-prop-name", uid)), Sense::click()); + if name_response.double_clicked() && super::timeline::reveal_effect_property(app, layer.id.0, uid) { + app.raise_panel(crate::dock::PanelKind::Timeline); + } app.auto.add(&format!("effectControls.prop.{uid}.name"), name_clip, &prop.name); let merge = format!("ec-{uid}"); // With several layers selected the edit applies to the same effect property of each (#491). diff --git a/crates/ui-egui/src/panels/timeline.rs b/crates/ui-egui/src/panels/timeline.rs index 163e6507..c7114a28 100644 --- a/crates/ui-egui/src/panels/timeline.rs +++ b/crates/ui-egui/src/panels/timeline.rs @@ -1134,6 +1134,21 @@ pub(crate) fn open_effect_paths(app: &mut EffectcraftApp, layer: u64, props: &[u app.ui.timeline.open_groups.extend(open); } +/// Show an Effect Controls property in its layer's Timeline Effects view. +pub(crate) fn reveal_effect_property(app: &mut EffectcraftApp, layer: u64, prop: u64) -> bool { + let Some(l) = app.session.active_comp().and_then(|c| c.layer(LayerId(layer))) else { return false }; + let Some(fx) = l.effects().map(|g| g.uid) else { return false }; + let path = enclosing_groups(l, prop); + if path.first() != Some(&fx) { + return false; + } + let tl = &mut app.ui.timeline; + tl.open_layers.insert(layer); + tl.layer_reveal.insert(layer, vec!["effects".into()]); + tl.open_groups.extend(path); + true +} + /// After a reveal shortcut that picks properties by state (EE expressions): those inside effects /// on `layers` show under their effect, twirled open. pub(crate) fn open_revealed(app: &mut EffectcraftApp, layers: &[u64], kinds: &[String]) { @@ -4317,6 +4332,32 @@ mod tests { assert!(labels(&app).iter().any(|r| r.trim() == "Scale")); } + #[test] + fn reveal_effect_property_opens_layer_effect_path_in_timeline() { + let mut app = app(); + let comp = app.session.active_comp().unwrap().clone(); + let bx = comp.layers.iter().find(|l| l.name == "Box").unwrap().id.0; + let prop = comp + .layer(LayerId(bx)) + .and_then(|layer| layer.effects()) + .and_then(|effects| effects.groups().next()) + .and_then(|effect| effect.get("blurriness")) + .unwrap() + .uid; + + assert!(reveal_effect_property(&mut app, bx, prop)); + assert!(app.ui.timeline.open_layers.contains(&bx)); + assert_eq!(app.ui.timeline.layer_reveal.get(&bx), Some(&vec!["effects".to_string()])); + + let rows = labels(&app); + let effect = rows.iter().position(|row| row.trim() == ">Gaussian Blur").unwrap(); + assert_eq!(rows.get(effect + 1).map(String::as_str).map(str::trim), Some("Blurriness"), "{rows:?}"); + assert!(rows.iter().any(|row| row.trim() == "Blur Dimensions"), "Effects view shows the effect's other properties too: {rows:?}"); + + let transform_prop = comp.layer(LayerId(bx)).and_then(|layer| layer.transform()).and_then(|group| group.get("position")).unwrap().uid; + assert!(!reveal_effect_property(&mut app, bx, transform_prop), "non-effect properties do not change the Effects view"); + } + #[test] fn columns_toggle_and_layout() { let mut app = app(); From 548001e1a9a0c3c170fe74b6a870f37d7469dd56 Mon Sep 17 00:00:00 2001 From: caldiag Date: Fri, 16 Oct 2026 14:55:17 -0300 Subject: [PATCH 2/2] fix: use timeline.revealProps from updated main instead of custom implementation, remove redundant test --- crates/ui-egui/src/panels/effect_controls.rs | 9 ++++- crates/ui-egui/src/panels/timeline.rs | 41 -------------------- 2 files changed, 7 insertions(+), 43 deletions(-) diff --git a/crates/ui-egui/src/panels/effect_controls.rs b/crates/ui-egui/src/panels/effect_controls.rs index 73798880..7aa40663 100644 --- a/crates/ui-egui/src/panels/effect_controls.rs +++ b/crates/ui-egui/src/panels/effect_controls.rs @@ -273,8 +273,13 @@ fn prop_row( app.auto.add(&format!("effectControls.prop.{uid}.name"), name_clip, &prop.name); p.with_clip_rect(name_clip.intersect(p.clip_rect())).text(pos2(swr.max.x + 6.0, cy), Align2::LEFT_CENTER, &prop.name, Tokens::ui(12.0), t.text); let name_response = ui.interact(name_clip, egui::Id::new(("ec-prop-name", uid)), Sense::click()); - if name_response.double_clicked() && super::timeline::reveal_effect_property(app, layer.id.0, uid) { - app.raise_panel(crate::dock::PanelKind::Timeline); + if name_response.double_clicked() { + app.ui.timeline.search.clear(); + app.ui.timeline.scroll_to = Some(crate::state::ScrollTo::Property(uid)); + if let Err(e) = crate::menus::frontend(app, ui.ctx(), "timeline.revealProps", json!({"props": [{"layer": layer.id.0, "prop": uid}]})) { + app.ui.status = e; + } + app.show_panel(crate::dock::PanelKind::Timeline); } app.auto.add(&format!("effectControls.prop.{uid}.name"), name_clip, &prop.name); let merge = format!("ec-{uid}"); diff --git a/crates/ui-egui/src/panels/timeline.rs b/crates/ui-egui/src/panels/timeline.rs index 789b1ff9..aff4ef2c 100644 --- a/crates/ui-egui/src/panels/timeline.rs +++ b/crates/ui-egui/src/panels/timeline.rs @@ -1134,21 +1134,6 @@ pub(crate) fn open_effect_paths(app: &mut EffectcraftApp, layer: u64, props: &[u app.ui.timeline.open_groups.extend(open); } -/// Show an Effect Controls property in its layer's Timeline Effects view. -pub(crate) fn reveal_effect_property(app: &mut EffectcraftApp, layer: u64, prop: u64) -> bool { - let Some(l) = app.session.active_comp().and_then(|c| c.layer(LayerId(layer))) else { return false }; - let Some(fx) = l.effects().map(|g| g.uid) else { return false }; - let path = enclosing_groups(l, prop); - if path.first() != Some(&fx) { - return false; - } - let tl = &mut app.ui.timeline; - tl.open_layers.insert(layer); - tl.layer_reveal.insert(layer, vec!["effects".into()]); - tl.open_groups.extend(path); - true -} - /// After a reveal shortcut that picks properties by state (EE expressions): those inside effects /// on `layers` show under their effect, twirled open. pub(crate) fn open_revealed(app: &mut EffectcraftApp, layers: &[u64], kinds: &[String]) { @@ -4385,32 +4370,6 @@ mod tests { assert!(labels(&app).iter().any(|r| r.trim() == "Scale")); } - #[test] - fn reveal_effect_property_opens_layer_effect_path_in_timeline() { - let mut app = app(); - let comp = app.session.active_comp().unwrap().clone(); - let bx = comp.layers.iter().find(|l| l.name == "Box").unwrap().id.0; - let prop = comp - .layer(LayerId(bx)) - .and_then(|layer| layer.effects()) - .and_then(|effects| effects.groups().next()) - .and_then(|effect| effect.get("blurriness")) - .unwrap() - .uid; - - assert!(reveal_effect_property(&mut app, bx, prop)); - assert!(app.ui.timeline.open_layers.contains(&bx)); - assert_eq!(app.ui.timeline.layer_reveal.get(&bx), Some(&vec!["effects".to_string()])); - - let rows = labels(&app); - let effect = rows.iter().position(|row| row.trim() == ">Gaussian Blur").unwrap(); - assert_eq!(rows.get(effect + 1).map(String::as_str).map(str::trim), Some("Blurriness"), "{rows:?}"); - assert!(rows.iter().any(|row| row.trim() == "Blur Dimensions"), "Effects view shows the effect's other properties too: {rows:?}"); - - let transform_prop = comp.layer(LayerId(bx)).and_then(|layer| layer.transform()).and_then(|group| group.get("position")).unwrap().uid; - assert!(!reveal_effect_property(&mut app, bx, transform_prop), "non-effect properties do not change the Effects view"); - } - #[test] fn columns_toggle_and_layout() { let mut app = app();