#1368: dragging an effect lights up the layer it will land on

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Kristian Myram
2026-10-14 00:59:11 +02:00
co-authored by Claude Sonnet 5.5
parent 549e9d8251
commit 9f02bd2a72
2 changed files with 51 additions and 1 deletions
+11 -1
View File
@@ -3330,8 +3330,18 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
{
let released = ctx.input(|i| i.pointer.any_released());
if let crate::panels::DragPayload::Effect(e) = payload.as_ref() {
p.rect_stroke(rows_rect, 0.0, Stroke::new(2.0, t.accent), StrokeKind::Inside);
let target = hit_rows.iter().find(|(r, _)| ptr.y >= r.min.y && ptr.y < r.max.y).map(|(_, row)| row.layer);
// The layer the effect would land on (its row and its open properties) is the one
// that lights up, not the whole timeline.
if let Some(l) = target
&& let Some(span) = hit_rows.iter().filter(|(_, row)| row.layer == l).map(|(r, _)| *r).reduce(|a, b| a.union(b))
{
let lit = span.intersect(rows_rect);
let rp = p.with_clip_rect(rows_rect);
rp.rect_filled(lit, 0.0, t.accent.gamma_multiply(0.18));
rp.rect_stroke(lit, 0.0, Stroke::new(2.0, t.accent), StrokeKind::Inside);
app.auto.add("timeline.dropTarget", lit, "Drop target layer");
}
if released && let Some(l) = target {
actions.push(("effect.apply".into(), json!({"effect": e, "layers": [l.0]})));
}
@@ -0,0 +1,40 @@
//! Dragging an effect over the Timeline lights up the layer it would land on, not the whole panel.
use effectcraft_engine::Session;
use effectcraft_ui_egui::{EffectcraftApp, panels::DragPayload};
use egui::{Event, Modifiers, PointerButton, Pos2, Rect, pos2, vec2};
use egui_kittest::Harness;
use serde_json::json;
fn rect(h: &Harness<'_, EffectcraftApp>, id: &str) -> Rect {
let e = h.state().auto.find(id).unwrap_or_else(|| panic!("missing {id}"));
Rect::from_min_size(pos2(e.rect[0], e.rect[1]), vec2(e.rect[2], e.rect[3]))
}
fn drag_to(h: &mut Harness<'_, EffectcraftApp>, p: Pos2) {
h.input_mut().events.push(Event::PointerMoved(p));
h.input_mut().events.push(Event::PointerButton { pos: p, button: PointerButton::Primary, pressed: true, modifiers: Modifiers::NONE });
egui::DragAndDrop::set_payload(&h.ctx, DragPayload::Effect("CC Bend It".into()));
h.run_steps(2);
}
#[test]
fn effect_drag_highlights_the_layer_under_the_pointer() {
let mut s = Session::default();
s.execute("comp.new", json!({"name": "Main", "width": 640, "height": 360, "duration": 4})).unwrap();
let a = s.execute("layer.newNull", json!({})).unwrap()["layer"].as_u64().unwrap();
let b = s.execute("layer.newNull", json!({})).unwrap()["layer"].as_u64().unwrap();
let mut h = Harness::builder().with_size(vec2(1600.0, 1000.0)).build_eframe(|_| EffectcraftApp::new(s));
h.run_steps(3);
assert!(h.state().auto.find("timeline.dropTarget").is_none(), "nothing is lit without a drag");
let (row_a, row_b) = (rect(&h, &format!("timeline.layer.{a}.row")), rect(&h, &format!("timeline.layer.{b}.row")));
let panel = rect(&h, "timeline.layerMarquee");
drag_to(&mut h, row_b.center());
let lit = rect(&h, "timeline.dropTarget");
assert!(lit.contains(row_b.center()) && !lit.contains(row_a.center()), "lit {lit:?} for row {row_b:?}");
assert!(lit.height() < panel.height(), "only the layer is lit, not the whole timeline");
drag_to(&mut h, row_a.center());
let lit = rect(&h, "timeline.dropTarget");
assert!(lit.contains(row_a.center()) && !lit.contains(row_b.center()), "the highlight follows the pointer: {lit:?}");
}