mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-03 06:52:21 -06:00
Marker names are drawn in a small outlined box, in theme colours
A named marker drew its name as bare text beside the flag. After Effects puts it in a small outlined box. The box uses the theme's field fill, field outline and text tokens, so it follows Dark, Darker and Light instead of a fixed grey. It applies to every marker with a name, composition markers included; the dimmed names of nested-comp markers on a precomp layer's bar are unchanged. Split out of the WAV markers change (#1423), where the review asked for it to be its own decision. Test: ui_marker_names renders the timeline in Dark and in Light, samples the box's fill and outline pixels, and checks they equal that theme's tokens and differ between the themes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
f3f24ef189
commit
4124ec6de7
@@ -298,7 +298,12 @@ fn marker(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter, comp:
|
||||
}
|
||||
p.add(egui::Shape::convex_polygon(marker_shape(x, y0, h), col, Stroke::NONE));
|
||||
if !m.comment.is_empty() {
|
||||
p.text(pos2(x + 7.0, y0 + h / 2.0), Align2::LEFT_CENTER, m.comment.lines().next().unwrap_or_default(), Tokens::ui(10.0), t.text);
|
||||
// The name sits in a small outlined box beside the flag, as in After Effects. It is drawn in the theme's field
|
||||
// colours, so it follows Dark, Darker and Light.
|
||||
let galley = p.layout_no_wrap(m.comment.lines().next().unwrap_or_default().to_string(), Tokens::ui(10.0), t.text);
|
||||
let box_rect = Rect::from_min_size(pos2(x + 6.0, y0), vec2(galley.size().x + 8.0, h.max(galley.size().y + 2.0)));
|
||||
p.rect(box_rect, t.radius_sm, t.field_bg, Stroke::new(1.0, t.field_border), egui::StrokeKind::Inside);
|
||||
p.galley(pos2(box_rect.min.x + 4.0, box_rect.center().y - galley.size().y / 2.0), galley, t.text);
|
||||
}
|
||||
let hit = Rect::from_min_max(pos2(x - 5.0, y0 - 1.0), pos2(x + 5.0, y1));
|
||||
let id = egui::Id::new(("marker", r.layer, r.index));
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
//! A marker's name is drawn in a small outlined box beside its flag, in the theme's own field colours (egui_kittest, a real
|
||||
//! render): the fill and the outline follow Dark and Light, and the two themes differ. `MARKER_NAMES_SNAPSHOT=/abs/dir`
|
||||
//! also saves the rendered panel for each theme.
|
||||
|
||||
use effectcraft_engine::Session;
|
||||
use effectcraft_ui_egui::EffectcraftApp;
|
||||
use effectcraft_ui_egui::theme::ThemeKind;
|
||||
use egui_kittest::Harness;
|
||||
use serde_json::json;
|
||||
|
||||
fn close(got: [u8; 4], want: egui::Color32) -> bool {
|
||||
got[..3].iter().zip(want.to_array()).all(|(a, b)| a.abs_diff(b) <= 3)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_name_box_follows_the_theme() {
|
||||
let mut s = Session::default();
|
||||
s.execute("comp.new", json!({"name": "Song", "width": 640, "height": 360, "duration": 4})).unwrap();
|
||||
s.execute("layer.newSolid", json!({"name": "Bed", "color": "#204060", "width": 640, "height": 360})).unwrap();
|
||||
s.execute("markers.set", json!({"new": true, "time": 1.0, "comment": "Verse"})).unwrap();
|
||||
|
||||
let mut h = Harness::builder().with_size(egui::vec2(1600.0, 1000.0)).build_eframe(move |_| EffectcraftApp::new(s));
|
||||
h.run_steps(4);
|
||||
let ctx = h.ctx.clone();
|
||||
|
||||
let mut seen = vec![];
|
||||
for (kind, name) in [(ThemeKind::Dark, "dark"), (ThemeKind::Light, "light")] {
|
||||
h.state_mut().set_theme(&ctx, kind);
|
||||
h.run_steps(4);
|
||||
let tokens = h.state().tokens;
|
||||
assert_eq!(tokens.kind, kind);
|
||||
// the flag's hit area is 10 wide, centred on the marker; the box starts 6 points right of the centre
|
||||
let hit = h.state().auto.find("timeline.marker.0").unwrap_or_else(|| panic!("the marker is on screen ({name})")).rect;
|
||||
let (x, y0) = (hit[0] + hit[2] / 2.0, hit[1] + 1.0);
|
||||
let h_flag = (hit[3] - 1.0).min(10.0);
|
||||
let image = h.render().expect("the panel renders");
|
||||
if let Some(dir) = std::env::var_os("MARKER_NAMES_SNAPSHOT") {
|
||||
image.save(std::path::Path::new(&dir).join(format!("marker-name-{name}.png"))).unwrap();
|
||||
}
|
||||
let scale = image.width() as f32 / 1600.0;
|
||||
let at = |px: f32, py: f32| image.get_pixel((px * scale) as u32, (py * scale) as u32).0;
|
||||
let mid = y0 + h_flag / 2.0;
|
||||
// inside the box, left of the text: the field fill; on its left edge: the field outline
|
||||
let fill = at(x + 6.0 + 2.5, mid);
|
||||
let edge = at(x + 6.0 + 0.5, mid);
|
||||
assert!(close(fill, tokens.field_bg), "{name}: box fill {fill:?}, the theme's field_bg is {:?}", tokens.field_bg);
|
||||
assert!(close(edge, tokens.field_border), "{name}: box outline {edge:?}, the theme's field_border is {:?}", tokens.field_border);
|
||||
seen.push((fill, edge));
|
||||
}
|
||||
assert_ne!(seen[0], seen[1], "the box looks different in Dark and in Light, so it is not a fixed grey");
|
||||
}
|
||||
Reference in New Issue
Block a user