mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 23:58:21 +00:00
Tools bar: take first-click modifiers from same-frame double-click releases.
When two primary releases land on a slot in one frame, derive prev_modified from the earlier release so an Alt-then-plain pair cannot create-on-double-click.
This commit is contained in:
1 parent
56974e7262
commit
55a6154ac7
1 file changed
+53
-7
@@ -105,28 +105,36 @@ fn tool_slot(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter, si:
|
||||
// Plain click selects the shown tool; Alt/Option-click cycles the flyout slot
|
||||
// (After Effects / Photoshop parity with the Shift+letter key cycle).
|
||||
// Prefer the primary-release event's modifiers: Alt may already be up by the
|
||||
// time this frame reads i.modifiers.
|
||||
let click_mods = ui.input(|i| {
|
||||
// time this frame reads i.modifiers. When a double-click lands as two releases
|
||||
// in one frame, the earlier release is the first click.
|
||||
let releases: Vec<egui::Modifiers> = ui.input(|i| {
|
||||
i.events
|
||||
.iter()
|
||||
.rev()
|
||||
.find_map(|e| match e {
|
||||
.filter_map(|e| match e {
|
||||
egui::Event::PointerButton {
|
||||
pos,
|
||||
button: egui::PointerButton::Primary,
|
||||
pressed: false,
|
||||
modifiers,
|
||||
..
|
||||
} => Some(*modifiers),
|
||||
} if resp.rect.contains(*pos) => Some(*modifiers),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or(i.modifiers)
|
||||
.collect()
|
||||
});
|
||||
let click_mods = releases.last().copied().unwrap_or_else(|| ui.input(|i| i.modifiers));
|
||||
let alt = click_mods.alt;
|
||||
let modified = click_mods.alt || click_mods.shift || click_mods.ctrl || click_mods.command;
|
||||
// egui's double-click ignores modifiers: remember whether the previous click
|
||||
// was modified so create-on-double-click only runs for two plain clicks.
|
||||
let prev_mod_id = id.with("click-mod");
|
||||
let prev_modified = ui.data(|d| d.get_temp::<bool>(prev_mod_id)).unwrap_or(false);
|
||||
let prev_modified = match releases.len() {
|
||||
n if n >= 2 => {
|
||||
let m = releases[n - 2];
|
||||
m.alt || m.shift || m.ctrl || m.command
|
||||
}
|
||||
_ => ui.data(|d| d.get_temp::<bool>(prev_mod_id)).unwrap_or(false),
|
||||
};
|
||||
let slot_click = resp.clicked() && !held;
|
||||
if slot_click {
|
||||
let pick = if slot.len() > 1 && alt {
|
||||
@@ -971,6 +979,44 @@ mod tests {
|
||||
assert_eq!(app.ui.tool, Tool::Type, "wraps back to Type");
|
||||
}
|
||||
|
||||
/// An Alt-click and a plain click that land as two releases in one frame must not
|
||||
/// create a text layer: the first click was modified.
|
||||
#[test]
|
||||
fn mixed_modifier_same_frame_double_click_does_not_create() {
|
||||
let mut s = effectcraft_engine::Session::default();
|
||||
s.execute("comp.new", json!({"width": 640, "height": 360, "duration": 2})).unwrap();
|
||||
let mut app = EffectcraftApp::new(s);
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::install(&ctx, &app.tokens, crate::i18n::language(&app));
|
||||
frame(&mut app, &ctx, 0.0, vec![]);
|
||||
frame(&mut app, &ctx, 0.1, vec![]);
|
||||
let e = app.auto.elements.iter().find(|w| w.id == "tools.Type").expect("Type slot");
|
||||
let at = egui::pos2(e.rect[0] + e.rect[2] / 2.0, e.rect[1] + e.rect[3] / 2.0);
|
||||
let alt = egui::Modifiers { alt: true, ..Default::default() };
|
||||
let plain = egui::Modifiers::default();
|
||||
let pointer = |pos, pressed, modifiers| egui::Event::PointerButton {
|
||||
pos,
|
||||
button: egui::PointerButton::Primary,
|
||||
pressed,
|
||||
modifiers,
|
||||
};
|
||||
app.ui.tool = Tool::Type;
|
||||
app.ui.slot_tools[10] = Tool::Type;
|
||||
frame(
|
||||
&mut app,
|
||||
&ctx,
|
||||
1.0,
|
||||
vec![
|
||||
egui::Event::PointerMoved(at),
|
||||
pointer(at, true, alt),
|
||||
pointer(at, false, alt),
|
||||
pointer(at, true, plain),
|
||||
pointer(at, false, plain),
|
||||
],
|
||||
);
|
||||
assert!(app.session.active_comp().unwrap().layers.is_empty(), "Alt then plain in one frame must not create");
|
||||
assert!(app.session.state.text_edit.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_clicking_creation_tools_makes_instances() {
|
||||
|
||||
Reference in new issue
Block a user